使用导航组件为每个片段自定义工具栏 [英] Custom Toolbar for each fragment using Navigation component

查看:39
本文介绍了使用导航组件为每个片段自定义工具栏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I use Navigation component with a single activity. The idea to create custom toolbar for each Fragment. For example one toolbar has to be yellow, another purple with menu icons, another transparent. And also if it possible I would like to implement it with saving connection between navigation and toolbar by setupActionBarWithNavController(navController) in MainActivity. I tried to use this method (activity as? AppCompatActivity)?.setSupportActionBar(toolbar) in Fragment but it duplicated 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()
    }
}

推荐答案

我尝试在 Fragment 中使用此方法 (activity as? AppCompatActivity)?.setSupportActionBar(toolbar) 但它复制了工具栏.

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

这是意料之中的,因为工具栏由活动托管,并且由于 Jetpack 导航架构组件使用单一活动模型,因此此活动托管的所有导航图片段都共享此工具栏(因为它是活动的一部分).

This is expected because the toolbar is hosted by the activity, and as Jetpack navigation architecture components uses a single-activity model, then all navGraph fragments hosted by this activity share this toolbar (because it's a part of the activity).

因此再次重置工具栏会复制它.

And therefore resetting the toolbar again will duplicate it.

对此的解决方案是从活动中移除工具栏,并在每个片段布局中使用唯一的工具栏,这样当一个片段与另一个片段进行交易时;旧片段的布局被新片段的新布局替换,所以旧的工具栏不见了,我们有了一个新的工具栏;而此时你需要为新的工具栏调用setSupportActionBar(toolbar).

The solution to this is to remove the toolbar from the activity, and use a unique toolbar within every fragment layout, this way when a fragment is transacted to another; the layout of the old fragment is replaced with the new layout of the new fragment, so the old toolbar is gone, and we've a new toolbar; and at this time you need to call setSupportActionBar(toolbar) for the new toolbar.

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

But notice that every time you call setSupportActionBar(toolbar) you have to recall setupActionBarWithNavController() because it needs to be attached to the new toolbar.

更新

所以,我必须在 Fragment 中调用 setSupportActionBar(toolbar) 和 setupActionBarWithNavController()?

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

其实你可以在activity中调用setSupportActionBar(toolbar).但是你可以在片段中使用 requireActivity() 来做到这一点:

Actually you can call setSupportActionBar(toolbar) in the activity. But you can use requireActivity() in fragment to do that:

为了不重复事情,你可以有一个函数来做到这一点:

In order not to repeat things, you can have a function the activity to do that:

活动中:

fun setupActionBar(toolBar: Toolbar) {

    setSupportActionBar(toolbar)

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

    navController = navHostFragment.navController

    setupActionBarWithNavController(navController)
    
}   

在片段中:

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

这篇关于使用导航组件为每个片段自定义工具栏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆