我正在寻找 setupWithNavController(Toolbar, NavController) 的 Compose 变体,以便在导航目的地发生变化时自动更新
AppBar
中的向上按钮。
到目前为止我还没有发现任何有用的东西。
Compose 中这被认为是糟糕的设计吗?或者是否有一些简单的方法可以实现我没有看到的相同效果?
我已经想出了一个解决方案,但我不满意。
androidx.navigation:navigation-compose:1.0.0-alpha08
提供了一个扩展函数来观察current返回堆栈条目。
@Composable
fun NavController.currentBackStackEntryAsState(): State<NavBackStackEntry?>
我创建了一个类似的扩展来观察前一个返回堆栈条目
/**
* Gets the previous navigation back stack entry as a [MutableState]. When the given navController
* changes the back stack due to a [NavController.navigate] or [NavController.popBackStack] this
* will trigger a recompose and return the second top entry on the back stack.
*
* @return a mutable state of the previous back stack entry
*/
@Composable
fun NavController.previousBackStackEntryAsState(): State<NavBackStackEntry?> {
val previousNavBackStackEntry = remember { mutableStateOf(previousBackStackEntry) }
// setup the onDestinationChangedListener responsible for detecting when the
// previous back stack entry changes
DisposableEffect(this) {
val callback = NavController.OnDestinationChangedListener { controller, _, _ ->
previousNavBackStackEntry.value = controller.previousBackStackEntry
}
addOnDestinationChangedListener(callback)
// remove the navController on dispose (i.e. when the composable is destroyed)
onDispose {
removeOnDestinationChangedListener(callback)
}
}
return previousNavBackStackEntry
}
以及后退按钮的可组合项
@Composable
fun NavigationIcon(navController: NavController): @Composable (() -> Unit)? {
val previousBackStackEntry: NavBackStackEntry? by navController.previousBackStackEntryAsState()
return previousBackStackEntry?.let {
{
IconButton(onClick = {
navController.popBackStack()
}) {
Icon(Icons.Default.ArrowBack, contentDescription = "Up button")
}
}
}
}
我必须返回
@Composable (() -> Unit)?
(而不是可组合函数常见的无返回值),因为 TopAppBar
使用可空性来检查是否将标题偏移 16dp(不带图标)或 72dp(带图标)。
最后,内容是这样的
@Composable
fun MainContent() {
val navController: NavHostController = rememberNavController()
Scaffold(
topBar = {
TopAppBar(
title = { Text("Weather") },
navigationIcon = { NavigationIcon(navController) }
)
},
) {
NavHost(
navController,
startDestination = "list"
) {
composable("list") {
...
}
composable("detail") {
...
}
}
}
}
创建自定义
NavigationTopAppBar
可组合项并将 NavController
从 NavigationIcon
中提升出来可能会更清晰,但想法保持不变。我没有费心进一步修补。
我还尝试根据 current NavGraph 目的地自动更新标题。不幸的是,没有一种可靠的方法可以在不从
androidx.navigation:navigation-compose
库中提取大量内部实现的情况下为目的地设置标签。