如何在切换导航目的地时刷新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
相关产品推荐
相关产品推荐

