android-fragments 是否从片段访问content_main.xml上的视图?

yfwxisqw  于 2022-11-13  发布在  Android
关注(0)|答案(1)|浏览(132)

在我的应用中,我使用了带有Fragments的NavController。在一些Fragments中,我需要访问MainActivity布局上的视图。我是这样做的:

val fab: FloatingActionButton = requireActivity().findViewById(R.id.fab)

这按预期正常工作。但是,有一个视图不想被调用,findViewById()返回null。
布局结构是这样的。在activity_main.xml

<androidx.drawerlayout.widget.DrawerLayout
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        ....>
        <FrameLayout
            android:id="@+id/frame"
            .... />
        <include
            android:id="@+id/include"
            layout="@layout/app_bar_main" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav"
        .... />
</androidx.drawerlayout.widget.DrawerLayout>

包含app_bar_main.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout 
    ....>

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        ....>

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing"
            ....>
            <com.google.android.material.appbar.MaterialToolbar
                android:id="@+id/toolbar"
                .... />
        </com.google.android.material.appbar.CollapsingToolbarLayout>

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

    <include
        android:id="@+id/content"
        layout="@layout/content_main" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        .... />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

包括content_main.xml

<androidx.core.widget.NestedScrollView 
    android:id="@+id/nested"
    ....>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/host"
        .... />
</androidx.core.widget.NestedScrollView>

问题是,我需要访问NestedScrollView,尽管所有其他视图都可以访问,但content_main.xml上的这个视图无法访问,并返回null:

java.lang.NullPointerException: requireActivity().findViewById(R.id.nested) must not be null

编辑:

class HomeFragment : Fragment() {
    private lateinit var drawer: DrawerLayout
    private lateinit var nested: NestedScrollView
    private lateinit var fab: FloatingActionBar
    private lateinit var bng: FragmentHomeBinding
    
    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
        setHasOptionsMenu(true)
        bng = FragmentHomeBinding.inflate(layoutInflater, container, false)
        return bng.root
    }
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        drawer = requireActivity().findViewById(R.id.drawer)
        fab = requireActivity().findViewById(R.id.fab)
        nested = requireActivity().findViewById(R.id.nested) // This line throws exception

        .........
    }
}

如您所见,我使用viewBinding来处理Fragment的Views。我不认为这会是个问题。

c8ib6hqw

c8ib6hqw1#

首先,我发现我需要重新排序我的XML布局,以便将content_main.xmlapp_bar_layout.xml的内容直接放到activity_main.xml中,如下所示:
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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"
    android:id="@+id/drawer"
    ...>

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

        <androidx.coordinatorlayout.widget.CoordinatorLayout
            android:id="@+id/coordinator"
            ...>

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

                <com.google.android.material.appbar.CollapsingToolbarLayout
                    android:id="@+id/collapsing"
                    ... >

                    <com.google.android.material.appbar.MaterialToolbar
                        android:id="@+id/toolbar"
                        ... />

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

            <androidx.core.widget.NestedScrollView
                android:id="@+id/nested"
                ... >

                <androidx.fragment.app.FragmentContainerView
                    android:id="@+id/host"
                    ... />
            </androidx.core.widget.NestedScrollView>

            <com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/fab"
                ... />

        </androidx.coordinatorlayout.widget.CoordinatorLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav"
        ... />
</androidx.drawerlayout.widget.DrawerLayout>

这可能不是一个最佳的方法,但如果没有这一步,content_main.xml上的View就不能被访问,这和以前一样令人困惑。我不知道,但看起来Google在它的库中改变了一些东西,或者应该是什么。
下一步,View您要从某个Fragment访问activity_main.xml上的View,您必须将它们设置为公共:
MainActivity.kt

class MainActivity : AppCompatActivity() {
    
    ...

    lateinit var fab: FloatingActionButton
    lateinit var nested: NestedScrollView

    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        ...

        nested = findViewById(R.id.nested)
        fab = findViewById(R.id.fab)
    
        ...
    }
}

现在,它们可以在Fragment中使用,如下所示:
MyFragment.kt

class MyFragment : Fragment() {

    ...

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_my, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        ...

        var fab: FloatingActionButton
        var nested: NestedScrollView

        (activity as MainActivity).apply {
            fab = this.fab
            nested = this.nested
        }

        ...
    }
}

就这样--这样,我就可以实现我的目标了。

相关问题