Android Compose setupWithNavController

Ant*_*nit 7 android android-navigation android-jetpack-compose

我正在寻找setupWithNavController(Toolbar, NavController)AppBar的 Compose 变体,以便在导航目的地发生变化时自动更新向上按钮。到目前为止我还没有发现任何有用的东西。

Compose 中是否认为这是一个糟糕的设计?或者是否有一些简单的方法可以实现我没有看到的相同目标?

Ant*_*nit 5

我已经找到了解决方案,但我不满意。


androidx.navigation:navigation-compose:1.0.0-alpha08提供了一个扩展函数来观察当前的返回堆栈条目。

@Composable
fun NavController.currentBackStackEntryAsState(): State<NavBackStackEntry?>
Run Code Online (Sandbox Code Playgroud)

我创建了一个类似的扩展来观察之前的返回堆栈条目

/**
 * 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
}
Run Code Online (Sandbox Code Playgroud)

以及后退按钮的可组合项

@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")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我必须返回 a @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") {
                ...
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

列表: 列表

细节: 细节

创建自定义NavigationTopAppBar可组合项并将其NavController提升出来可能会更清晰NavigationIcon,但想法保持不变。我没有再费心去进一步修修补补。


我还尝试根据当前的NavGraph 目的地自动更新标题。不幸的是,没有一种可靠的方法可以在不从库中提取大量内部实现的情况下为目的地设置标签androidx.navigation:navigation-compose