导航组件,如何在导航抽屉中显示普通 UP/back 按钮而不是汉堡包图标
Navigation Component, how to show a normal UP/back button instead of hamburger icon in Navigation Drawer
我的 activity 中有三个顶级目标片段:
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.trackerFragment,
R.id.nutrientFragment,
R.id.settingsFragment
),
drawerLayout
)
这意味着所有这些片段都将显示汉堡包按钮,而不是正常的后退箭头。问题是我的应用程序中有一个“转到营养”按钮,该按钮导航到顶级目的地 NutrientFragment。我希望这个片段在使用抽屉导航时仍然显示汉堡包图标,但在通过“转到营养”按钮导航时显示正常的 back/up 按钮。
我最初的想法是在导航到 NutrientFragment
时传递一个布尔值作为参数,并在 onCreateView()
内部,根据布尔值,删除汉堡包图标或添加后面的按钮。但这似乎有点丑陋和低效,特别是如果将来我添加更多可能有同样问题的目的地。我也不知道如何“删除汉堡包图标并替换为正常的后退按钮”。关于如何实施的任何想法?我找到的所有答案要么是旧的已弃用 java 代码,要么不是我想要的。
谢谢。
给定:
现在您有一个包含三个片段(trackerFragment、nutrientFragment 和 settingsFragment)的导航抽屉。
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.trackerFragment,
R.id.nutrientFragment,
R.id.settingsFragment
),
drawerLayout
)
必填:
您想将汉堡保留在主页片段 (NutrientFragment
) 中,并将其替换为某些片段的向上按钮。
解法:
假设 settingsFragment
是片段是你需要有向上按钮而不是汉堡。
首先从 appBarConfiguration
中删除此片段:
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.trackerFragment, R.id.nutrientFragment
), drawerLayout
)
然后,为了控制 Burger 按钮,您需要将抽屉布局和 SupportActionBar
与 ActionBarDrawerToggle
同步,这里是方法:
fun getActionBarDrawerToggle(
drawerLayout: DrawerLayout,
toolbar: Toolbar
): ActionBarDrawerToggle {
val toggle = ActionBarDrawerToggle(
this,
drawerLayout,
toolbar,
R.string.open,
R.string.close
)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
return toggle
}
R.string.open
& R.string.close
是符号字符串,可以在 strings.xml:
中创建它们
<resources>
<string name="open">Open</string>
<string name="close">Close</string>
</resources>
而 toolBar
是从布局中膨胀并设置为 supportActionBar
和 setSupportActionBar()
的工具栏
然后,向导航添加侦听器以检测何时选择 settingFragment
,以便您可以使用 toggle.isDrawerIndicatorEnabled
:
禁用汉堡的切换功能
val toggle = getActionBarDrawerToggle(drawerLayout, toolbar) // replace the `drawerLayout` & `toolbar` according to yours
navController.addOnDestinationChangedListener { _, destination, _ ->
if (destination.id == R.id.settingsFragment)
toggle.isDrawerIndicatorEnabled = false
}
当然,现在 UP 按钮在您单击它时将不起作用,要解决此问题,我们需要 setToolbarNavigationClickListener
以启用切换功能并导航回主页片段(假设主页片段是 nutrientFragment
):
toggle.setToolbarNavigationClickListener {
toggle.isDrawerIndicatorEnabled = true
navController.navigate(R.id.nutrientFragment)
}
预览:
这是 Gallery 片段,UP 按钮所在的位置:
我设法找到了解决方案。我将这个变量添加到我的 MainActivity:
// If true, disable drawer and enable back/up button
private var isUpButton = false
还有这些方法:
// Disable drawer and enable the up button
fun useUpButton() {
supportActionBar?.setHomeAsUpIndicator(
androidx.appcompat.R.drawable.abc_ic_ab_back_material
)
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
isUpButton = true
}
// Enable the drawer and disable up button
private fun useHamburgerButton() {
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
isUpButton = false
}
useUpButton() 将汉堡包图标替换为默认的向上图标,锁定抽屉滑块并将 isUpButton 设置为 true。我还覆盖了 onOptionsItemsSelected:
// If isUpButton is true, and the home button is clicked, navigate up and
// enable drawer again, if false, just normal drawer behaviour
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (isUpButton && item.itemId == android.R.id.home) {
navController.navigateUp()
useHamburgerButton()
true
} else super.onOptionsItemSelected(item)
}
因此,如果单击主页按钮(汉堡包图标或向上图标),并且 isUpButton 设置为 true,activity 将向上导航,就像正常的向上行为一样,并将 isUpButton 重置为false,所以其他片段可以再次享受抽屉。
现在我需要做的就是使用这些方法来解决我的问题:我希望 NutrientFragment 仅在我不使用抽屉导航到它时显示“向上按钮”。为此,我需要在 nav_graph.xml:
上为 NutrientFragment 目标创建一个参数
<fragment
android:id="@+id/nutrientFragment"
android:name="com.example.elegantcalorietracker.ui.fragments.NutrientFragment"
android:label="@string/nutrients"
tools:layout="@layout/fragment_nutrient">
<action
android:id="@+id/action_nutrientFragment_to_trackerFragment"
app:destination="@id/trackerFragment" />
<argument
android:name="upButtonNeeded"
android:defaultValue="false"
app:argType="boolean" />
并将其添加到 NutrientFragment 的 onCreateView() 方法中:
upButtonNeeded = arguments?.getBoolean("upButtonNeeded") ?: false
if (upButtonNeeded) {
(activity as MainActivity).useUpButton()
}
现在,如果我在另一个片段中有一个导航到 NutrientFragment 的按钮,我需要做的就是将 true 作为参数传递给导航方法:
val argument = bundleOf("upButtonNeeded" to true)
this@TrackerFragment
.findNavController()
.navigate(
R.id.action_trackerFragment_to_nutrientFragment,
argument
)
结果:
当使用抽屉导航到 NutrientFragment 时,汉堡包图标正常显示,但当以其他方式导航到它时,如按钮,向上按钮显示:
我的 activity 中有三个顶级目标片段:
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.trackerFragment,
R.id.nutrientFragment,
R.id.settingsFragment
),
drawerLayout
)
这意味着所有这些片段都将显示汉堡包按钮,而不是正常的后退箭头。问题是我的应用程序中有一个“转到营养”按钮,该按钮导航到顶级目的地 NutrientFragment。我希望这个片段在使用抽屉导航时仍然显示汉堡包图标,但在通过“转到营养”按钮导航时显示正常的 back/up 按钮。
我最初的想法是在导航到 NutrientFragment
时传递一个布尔值作为参数,并在 onCreateView()
内部,根据布尔值,删除汉堡包图标或添加后面的按钮。但这似乎有点丑陋和低效,特别是如果将来我添加更多可能有同样问题的目的地。我也不知道如何“删除汉堡包图标并替换为正常的后退按钮”。关于如何实施的任何想法?我找到的所有答案要么是旧的已弃用 java 代码,要么不是我想要的。
谢谢。
给定:
现在您有一个包含三个片段(trackerFragment、nutrientFragment 和 settingsFragment)的导航抽屉。
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.trackerFragment,
R.id.nutrientFragment,
R.id.settingsFragment
),
drawerLayout
)
必填:
您想将汉堡保留在主页片段 (NutrientFragment
) 中,并将其替换为某些片段的向上按钮。
解法:
假设 settingsFragment
是片段是你需要有向上按钮而不是汉堡。
首先从 appBarConfiguration
中删除此片段:
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.trackerFragment, R.id.nutrientFragment
), drawerLayout
)
然后,为了控制 Burger 按钮,您需要将抽屉布局和 SupportActionBar
与 ActionBarDrawerToggle
同步,这里是方法:
fun getActionBarDrawerToggle(
drawerLayout: DrawerLayout,
toolbar: Toolbar
): ActionBarDrawerToggle {
val toggle = ActionBarDrawerToggle(
this,
drawerLayout,
toolbar,
R.string.open,
R.string.close
)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
return toggle
}
R.string.open
& R.string.close
是符号字符串,可以在 strings.xml:
<resources>
<string name="open">Open</string>
<string name="close">Close</string>
</resources>
而 toolBar
是从布局中膨胀并设置为 supportActionBar
和 setSupportActionBar()
然后,向导航添加侦听器以检测何时选择 settingFragment
,以便您可以使用 toggle.isDrawerIndicatorEnabled
:
val toggle = getActionBarDrawerToggle(drawerLayout, toolbar) // replace the `drawerLayout` & `toolbar` according to yours
navController.addOnDestinationChangedListener { _, destination, _ ->
if (destination.id == R.id.settingsFragment)
toggle.isDrawerIndicatorEnabled = false
}
当然,现在 UP 按钮在您单击它时将不起作用,要解决此问题,我们需要 setToolbarNavigationClickListener
以启用切换功能并导航回主页片段(假设主页片段是 nutrientFragment
):
toggle.setToolbarNavigationClickListener {
toggle.isDrawerIndicatorEnabled = true
navController.navigate(R.id.nutrientFragment)
}
预览:
这是 Gallery 片段,UP 按钮所在的位置:
我设法找到了解决方案。我将这个变量添加到我的 MainActivity:
// If true, disable drawer and enable back/up button
private var isUpButton = false
还有这些方法:
// Disable drawer and enable the up button
fun useUpButton() {
supportActionBar?.setHomeAsUpIndicator(
androidx.appcompat.R.drawable.abc_ic_ab_back_material
)
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
isUpButton = true
}
// Enable the drawer and disable up button
private fun useHamburgerButton() {
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
isUpButton = false
}
useUpButton() 将汉堡包图标替换为默认的向上图标,锁定抽屉滑块并将 isUpButton 设置为 true。我还覆盖了 onOptionsItemsSelected:
// If isUpButton is true, and the home button is clicked, navigate up and
// enable drawer again, if false, just normal drawer behaviour
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (isUpButton && item.itemId == android.R.id.home) {
navController.navigateUp()
useHamburgerButton()
true
} else super.onOptionsItemSelected(item)
}
因此,如果单击主页按钮(汉堡包图标或向上图标),并且 isUpButton 设置为 true,activity 将向上导航,就像正常的向上行为一样,并将 isUpButton 重置为false,所以其他片段可以再次享受抽屉。
现在我需要做的就是使用这些方法来解决我的问题:我希望 NutrientFragment 仅在我不使用抽屉导航到它时显示“向上按钮”。为此,我需要在 nav_graph.xml:
上为 NutrientFragment 目标创建一个参数<fragment
android:id="@+id/nutrientFragment"
android:name="com.example.elegantcalorietracker.ui.fragments.NutrientFragment"
android:label="@string/nutrients"
tools:layout="@layout/fragment_nutrient">
<action
android:id="@+id/action_nutrientFragment_to_trackerFragment"
app:destination="@id/trackerFragment" />
<argument
android:name="upButtonNeeded"
android:defaultValue="false"
app:argType="boolean" />
并将其添加到 NutrientFragment 的 onCreateView() 方法中:
upButtonNeeded = arguments?.getBoolean("upButtonNeeded") ?: false
if (upButtonNeeded) {
(activity as MainActivity).useUpButton()
}
现在,如果我在另一个片段中有一个导航到 NutrientFragment 的按钮,我需要做的就是将 true 作为参数传递给导航方法:
val argument = bundleOf("upButtonNeeded" to true)
this@TrackerFragment
.findNavController()
.navigate(
R.id.action_trackerFragment_to_nutrientFragment,
argument
)
结果:
当使用抽屉导航到 NutrientFragment 时,汉堡包图标正常显示,但当以其他方式导航到它时,如按钮,向上按钮显示: