Android Jetpack Navigation 如何处理 Toolbar 和 BottomNavBar 内容

Android Jetpack Navigation How to handle the Toolbar and BottomNavBar content

我对导航组件如何适应应用程序行为感到有点困惑。在教程中,一切看起来都不错而且闪亮,你不会做太复杂的事情,但在实际应用程序中实施时,情况似乎有所不同。

导航前

在实施导航之前,我不得不手动 运行 分段交易。为了做到这一点,我的片段将实现一个接口 onFragmentAction,它将 bundle 传递给主 Activity 并在 activity 中基于操作,替换当前片段与另一个。

第二个需要处理的部分是顶部工具栏和 BottomAppBar。例如 BottomAppBar 需要让 FAB 在某些片段上以不同方式对齐或隐藏在其他片段中。此外,顶部 ToolBar 需要在某些上展开或在其他上折叠。为此,我听取了 FragmentManager.OnBackStackChangedListener 并根据片段标记 getSupportFragmentManager().getBackStackEntryAt(size - 1).getName() 相应地更改了布局。

带导航

第一部分似乎很容易做:传递参数并开始新的片段。但我不知道导航是否可以处理工具栏管理,或者我需要从我的 Activity 继续管理它。

工具栏标题是根据导航图中的 'label' 值设置的,如果您想对工具栏或 BottomAppBar 做一些不同的事情,您可以在 activity 中添加 addOnNavigatedListener,并基于当前目的地做点什么。

findNavController(nav_host_fragment).addOnNavigatedListener { controller, 
 destination ->
 when(destination.id) {
    R.id.destination1 -> {
        //Do something with your toolbar or BottomAppBar
    }
    R.id.destination2 -> {
        //Do something with your toolbar or BottomAppBar
    }

 }
}

尽管 Alex 的解决方案有效,但我不推荐将其用于管理工具栏。

工具栏应该是片段布局的一部分,每个片段都应该管理自己的工具栏。您可以为每个片段添加不同的菜单。即使在想要在 activity 中使用工具栏的情况下,我也建议获取对工具栏形式 activity 的引用(通过界面),然后在片段本身中添加和操作其项目。

这将分离您的 activity 和片段(这是拥有导航图和路由器的目标之一)。一个好的经验法则是假设您想删除片段,那么您不需要对 activity.

进行任何更改

在你的片段中:

NavController navHostFragment = NavHostFragment.findNavController(this);
NavigationUI.setupWithNavController(toolbar, navHostFragment);

当我单击列表项 (Explore Fragment) 上的项目时,它会否定 DetailFragment,当我单击工具栏上的后退按钮时,它会 return MainFragment .

如果您想通过调用菜单项到达另一个片段,您必须为项目 id 提供与目标 id 中相同的 id。

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return 
       item.onNavDestinationSelected(findNavController(R.id.nav_host_fragment))
            || super.onOptionsItemSelected(item)
}


<item android:id="@+id/dailyInfoFragment"
      android:title="@string/action_settings"
      android:orderInCategory="100"
      app:showAsAction="never"/>


    <fragment
        android:id="@+id/dailyInfoFragment"
        android:name="com.example.sonyadmin.infoPerDay.DailyInfoFragment"
        android:label="fragment_daily_info"
        tools:layout="@layout/fragment_daily_info"
        />