【问题标题】:Custom Toolbar for each fragment using Navigation component使用导航组件的每个片段的自定义工具栏
【发布时间】:2021-06-26 03:27:37
【问题描述】:

我使用带有单个活动的导航组件。为每个片段创建自定义工具栏的想法。例如,一个工具栏必须是黄色的,另一个带有菜单图标的紫色,另一个是透明的。如果可能的话,我想通过 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()
    }
}

【问题讨论】:

    标签: android kotlin android-fragments android-toolbar android-architecture-navigation


    【解决方案1】:

    我尝试在 Fragment 中使用此方法(活动为?AppCompatActivity)?.setSupportActionBar(toolbar),但它重复了工具栏。

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

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

    解决方案是从活动中删除工具栏,并在每个片段布局中使用唯一的工具栏,这样当一个片段被交易给另一个片段时;旧片段的布局被新片段的新布局替换,所以旧的工具栏不见了,我们有了一个新的工具栏;此时您需要调用setSupportActionBar(toolbar) 来获取新工具栏。

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

    更新

    那么,我必须在 Fragment 中调用 setSupportActionBar(toolbar) 和 setupActionBarWithNavController() 吗?

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

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

    活动中:

    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)
    

    【讨论】:

    • 那么,我必须在 Fragment 中调用 setSupportActionBar(toolbar) 和 setupActionBarWithNavController() 吗?
    • @Artem 您可以通过requireActivity() 获取活动以setSupportActionBar,请查看答案中的更新部分
    • @Artem 嗨,这适用于 bottomNavigationBar 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多