You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在切换导航目的地时刷新TopAppBar的Lifted状态?

解决TopAppBar切换到不可滚动页面后保持抬起状态的问题

核心思路:监听当前导航目的地,切换到不可滚动页面时主动重置TopAppBar的滚动状态,让它回到非抬起状态。

具体实现

1. 标记路由的滚动属性

给TopLevelRoute新增字段,用来标记对应页面是否支持滚动:

data class TopLevelRoute<T : Any>(
    val name: String,
    val route: T,
    val icon: ImageVector,
    val isScrollable: Boolean // 新增:标记页面是否可滚动
)

2. 更新路由列表配置

给每个路由设置对应的滚动状态:

val topLevelRoutes = listOf(
    TopLevelRoute("Training", Training, Icons.Default.Lightbulb, isScrollable = false),
    TopLevelRoute("Statistics", Statistics, Icons.Default.AutoGraph, isScrollable = true)
)

3. 监听路由变化并重置状态

在HomeScreen中监听当前导航条目,切换到不可滚动页面时,重置TopAppBar的滚动偏移量:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen() {
    // ... 原有代码保持不变

    val navBackStackEntry by navController.currentBackStackEntryAsState()
    // 匹配当前路由的配置
    val currentRouteConfig = navBackStackEntry?.destination?.let { dest ->
        topLevelRoutes.find { dest.hasRoute(it.route::class) }
    }

    // 路由切换时重置TopAppBar状态
    LaunchedEffect(currentRouteConfig) {
        if (currentRouteConfig?.isScrollable == false) {
            // 将滚动偏移量重置为0,TopAppBar自动退出抬起状态
            scrollBehavior.state.scrollTo(0)
        }
    }

    // ... 原有Scaffold、NavHost代码保持不变
}

原理说明

pinnedScrollBehavior的抬起状态由内部TopAppBarState的滚动偏移量控制:当偏移量大于0时,TopAppBar进入抬起状态。切换到不可滚动页面时,调用scrollTo(0)把偏移量重置为0,TopAppBar就会回到初始的非抬起状态。

替代方案(无需修改TopLevelRoute)

如果不想修改路由类,也可以直接通过路由类型判断:

val navBackStackEntry by navController.currentBackStackEntryAsState()
val isCurrentPageScrollable = navBackStackEntry?.destination?.hasRoute(Statistics::class) == true

LaunchedEffect(isCurrentPageScrollable) {
    if (!isCurrentPageScrollable) {
        scrollBehavior.state.scrollTo(0)
    }
}

内容的提问来源于stack exchange,提问作者BenjyTec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:47:10