android - 使用导航组件为每个 fragment 自定义工具栏

我将导航组件用于单个 Activity 。为每个 fragment 创建自定义工具栏的想法。例如,一个工具栏必须是黄色的,另一个带有菜单图标的紫色工具栏,另一个是透明的。如果可能的话,我想通过 MainActivity 中的 setupActionBarWithNavController(navController) 保存导航和工具栏之间的连接来实现它。 我尝试在 Fragment 中使用此方法 (activity as?AppCompatActivity)?.setSupportActionBar(toolbar) 但它复制了工具栏。

这是我的主题

<style name="Theme.Movies" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>

这是MainActivity布局中的工具栏

 <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/purple_700"
        android:elevation="4dp"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:layout_constraintTop_toTopOf="parent" />

这是 MainActivity

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private lateinit var navController: NavController

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

        val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment

        navController = navHostFragment.navController

        setupActionBarWithNavController(navController)
        bottom_nav.setupWithNavController(navController)

    }

    override fun onSupportNavigateUp(): Boolean {
        return navController.navigateUp() || super.onSupportNavigateUp()
    }
}

最佳答案

I tried to use this method (activity as? AppCompatActivity)?.setSupportActionBar(toolbar) in Fragment but it duplicated toolbar.

这是预期的,因为工具栏由 Activity 托管,并且由于 Jetpack 导航架构组件使用单 Activity 模型,因此此 Activity 托管的所有 navGraph fragment 共享此工具栏(因为它是 Activity 的一部分)。

因此再次重置工具栏将复制它。

这个问题的解决方案是从 Activity 中删除工具栏,并在每个 fragment 布局中使用唯一的工具栏,这样当一个 fragment 被交易到另一个 fragment 时;旧 fragment 的布局被新 fragment 的新布局所取代,所以旧的工具栏不见了,我们有了一个新的工具栏;而此时你需要为新的工具栏调用setSupportActionBar(toolbar)

但请注意,每次调用 setSupportActionBar(toolbar) 时,您都必须调用 setupActionBarWithNavController(),因为它需要附加到新的工具栏。

更新

So, I have to call setSupportActionBar(toolbar) and setupActionBarWithNavController() in Fragment?

实际上你可以在 Activity 中调用setSupportActionBar(toolbar)。但是您可以在 fragment 中使用 requireActivity() 来做到这一点:

为了不重复事情,你可以有一个 Activity 的功能来做到这一点:

Activity 中:

fun setupActionBar(toolBar: Toolbar) {

    setSupportActionBar(toolbar)

    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment

    navController = navHostFragment.navController

    setupActionBarWithNavController(navController)
    
}   

在 fragment 中:

val toolbar = findViewById<Toolbar>(R.id.foo)
(requireActivity() as MainActivity).setupActionBar(toolbar)

https://stackoverflow.com/questions/68138959/

相关文章:

php - 找不到 Heroku 类 'NumberFormatter'

android - Room - 模式导出目录未提供给注释处理器,因此我们无法导入模式

node.js - 如何使用 cmd 更新 Node.js?

python - 如何在 python 数据框中做季度?

github-actions - 如何获取用户名,负责在 github 操作中触发工作流

algorithm - K个桶中N个对象的所有可能组合

pandas - 设置 pandas 索引单元格的背景颜色

flutter - 如何将 'Function' 类型的参数分配给 'void Function()

kubernetes - 无法使用 Terraform 为 AKS 集群创建命名空间,报告没有此类主

r - 将 100 个数据帧合并为一个数据帧的函数