首页 > 解决方案 > 导航组件:如何在每个片段中设置带有工具栏的抽屉

问题描述

我正在使用导航组件,并希望将抽屉布局与每个片段中的工具栏连接起来,而不是活动。

我尝试了这个在 onViewCreated() 上调用的答案,但是从活动中引用的任何视图都是空的。我猜这是因为片段在从活动的 onCreate 方法返回之前在布局中膨胀。

我使用此扩展函数将抽屉与片段的工具栏连接起来,我尝试从 onCreateView() 和 onViewCreated() 调用它,但没有工作,并且活动的抽屉布局始终为空。我只在从 onStart() 调用它时才工作,但我认为这不是正确的方法:

private fun AppCompatActivity.setToolbar() {
    setSupportActionBar(binding.toolbar)
    setHasOptionsMenu(true)
    val drawer = findViewById<DrawerLayout>(R.id.drawer)
    binding.toolbar.setupWithNavController(findNavController(), drawer)
}

调用此函数的正确位置是什么?

标签: androidnavigation-drawerandroid-architecture-navigationandroid-navigationandroid-navigation-graph

解决方案


当您调用setContentView(R.id.activity_layout)时,整个视图层次结构首先被膨胀,然后附加到 Activity。只有在setContentView()返回后findViewById()才能找到任何新膨胀的视图。

当您使用<fragment>标签时,片段的视图及其所有子片段的视图将作为该膨胀调用的一部分同步创建。这意味着在调用和方法时还setContentView()没有完成。这就是调用返回 null 的原因 - 活动的视图实际上还没有完成创建。onCreateView()onViewCreated()findViewById()

FragmentContainerView是专门为避免这些特殊情况而构建的,而是使用与其他片段相同的机制——即,它只是使用法线FragmentTransaction来添加你的片段——就像你自己在方法中调用beginTransaction()+一样。这意味着 Fragment 不会被强制同步创建其视图作为 的一部分,而是可以在返回后与其他所有 Fragment 一起创建。这就是允许或工作的原因。commitNow()onCreate()setContentView() setContentView()findViewById()onCreateView()onViewCreated()


推荐阅读