简体   繁体   中英

How to access a view from parent layout with ViewBinding?

I have a layout that contains a view pager and a fab. The view pager has fragments as pages. What I want is to access the FAB from inside a fragment.

fragment_user_anime_list(parent)

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context="com.destructo.sushi.ui.user.animeList.MyAnimeListFragment">

        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:fitsSystemWindows="true">

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                style="@style/ToolBarWithNavigation"
                android:layout_width="match_parent"
                android:layout_height="?actionBarSize"
                app:layout_scrollFlags="scroll|enterAlways"
                app:popupTheme="@style/PopupMenu"
                app:title="@string/my_anime_list"
                app:titleTextAppearance="@style/TextAppearance.Sushi.H1" />

            <com.google.android.material.tabs.TabLayout
                android:id="@+id/my_anime_list_tablayout"
                style="@style/TabLayoutStyle"
                android:layout_width="fill_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:tabIndicator="@drawable/custom_tab_layout_indicator"
                app:tabMode="scrollable" />

        </com.google.android.material.appbar.AppBarLayout>

        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/my_anime_list_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

        <ProgressBar
            android:id="@+id/progressbar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            android:layout_gravity="center"
            />

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/random_fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="@dimen/margin_normal"
            android:layout_marginBottom="@dimen/margin_normal"
            android:layout_gravity="bottom|right"
            android:src="@drawable/ic_question_line"
            app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"
            />

    </androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

fragment_my_anime_list(child viewpager page)

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/userAnimeRecycler"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:orientation="vertical"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            app:layout_constraintBottom_toTopOf="@+id/user_anime_list_pagination_progressbar"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ProgressBar
            android:id="@+id/user_anime_list_progressbar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/userAnimeRecycler" />

        <ProgressBar
            android:id="@+id/user_anime_list_pagination_progressbar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />



    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

in the child fragment


    private lateinit var binding: FragmentUserAnimeListBinding
    private lateinit var randomAnimeFab: FloatingActionButton


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentUserAnimeListBinding
            .inflate(inflater, container, false).apply {
                lifecycleOwner = viewLifecycleOwner
            }

        randomAnimeFab = binding.root.random_fab

        return binding.root
    }

This throws Null pointer exception. view cannot be null

How do I get a reference to the fab using viewBinding?

I found a solution without using view binding. Don't know if it's the best one. You get the parentfragment and reference it's views directly.

val fab = requireParentFragment().random_fab

and then you can check if it's null and do whatever you want

fab?.let{
   //Do something
}

If anyone knows how to do it using viewBinding let me know.

How do I get a reference to the fab using viewBinding?

Now you want to access the FAB from one of ViewPager pages/fragments through data binding.

Normally views should be accessed within its lifecycle owner (ie its activity/fragment), so views of the parent fragment (which hosts the FAB & the ViewPager), should be touched by this fragment, not by a page fragment.

You did a milestone by using requireParentFragment() .

val fab = requireParentFragment().random_fab

But instead of referencing the FAB directly from the page, you can create a method in the parent fragment instead and access this method from the page. And do the changes on FAB on this method.

And through this method, you can pass data between a page and the parentFragment without having to touch views of a fragment from another fragment.

So you could have a method in the parent fragment:

fun changeMyFab() {
    binding.random_fab ...
}

And call requireParentFragment().changeMyFab() from the page, and you can pass some data as method parameters to change the FAB behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM