首页 > 解决方案 > 从片段访问 content_main.xml 的视图?

问题描述

在我的应用程序中,我使用NavControllerFragments。在某些片段中,我需要访问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 的Viewss。我不认为这可能是问题。

标签: androidkotlinandroid-fragments

解决方案


因此,如果有人应该寻找解决方案,这里有一个对我有用的解决方案。首先,我发现我需要重新排序我的XML布局,以便将 thecontent_main.xml和 the的内容app_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>

这可能不是最佳方式,但如果没有这一步,Views oncontent_main.xml就无法访问,这在正常工作之前确实是胡说八道。实际上,不知道,但似乎谷歌改变了它的库中的一些东西或者任何应该的东西。

下一步,View如果你想activity_main.xml从某个地方访问Fragment,你必须将它们公开:

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
        }

        ...
    }
}

这就是所有的家伙!通过这种方式,我可以实现我的目标。

如上所述,这可能不是最佳方式,但它对我有用。

希望这可以帮助某人解决此类问题。

欢迎和赞赏任何改进或建议。


推荐阅读