使用导航组件为每个片段自定义工具栏
Custom Toolbar for each fragment using Navigation component
我将导航组件与单个 activity 结合使用。为每个片段创建自定义工具栏的想法。例如,一个工具栏必须是黄色的,另一个带有菜单图标的紫色工具栏,另一个是透明的。如果可能的话,我想通过在 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 模型,因此所有 navGraph 片段都由此 activity 托管分享此工具栏(因为它是 activity 的一部分)。
因此再次重置工具栏将复制它。
这个问题的解决方案是从 activity 中删除工具栏,并在每个片段布局中使用唯一的工具栏,这样当一个片段被交易到另一个片段时;旧片段的布局被新片段的新布局所取代,所以旧的工具栏不见了,我们有了一个新的工具栏;而此时你需要为新的工具栏调用setSupportActionBar(toolbar)
但请注意,每次调用 setSupportActionBar(toolbar)
时都必须调用 setupActionBarWithNavController()
,因为它需要附加到新工具栏。
更新
So, I have to call setSupportActionBar(toolbar) and setupActionBarWithNavController() in Fragment?
其实你可以在activity中调用setSupportActionBar(toolbar)
。但是你可以在片段中使用 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)
}
在片段中:
val toolbar = findViewById<Toolbar>(R.id.foo)
(requireActivity() as MainActivity).setupActionBar(toolbar)
我将导航组件与单个 activity 结合使用。为每个片段创建自定义工具栏的想法。例如,一个工具栏必须是黄色的,另一个带有菜单图标的紫色工具栏,另一个是透明的。如果可能的话,我想通过在 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 模型,因此所有 navGraph 片段都由此 activity 托管分享此工具栏(因为它是 activity 的一部分)。
因此再次重置工具栏将复制它。
这个问题的解决方案是从 activity 中删除工具栏,并在每个片段布局中使用唯一的工具栏,这样当一个片段被交易到另一个片段时;旧片段的布局被新片段的新布局所取代,所以旧的工具栏不见了,我们有了一个新的工具栏;而此时你需要为新的工具栏调用setSupportActionBar(toolbar)
但请注意,每次调用 setSupportActionBar(toolbar)
时都必须调用 setupActionBarWithNavController()
,因为它需要附加到新工具栏。
更新
So, I have to call setSupportActionBar(toolbar) and setupActionBarWithNavController() in Fragment?
其实你可以在activity中调用setSupportActionBar(toolbar)
。但是你可以在片段中使用 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)
}
在片段中:
val toolbar = findViewById<Toolbar>(R.id.foo)
(requireActivity() as MainActivity).setupActionBar(toolbar)