如何让TopAppBar返回按钮与系统返回按钮保持LazyColumn位置一致?
问题:TopAppBar返回按钮重置LazyColumn滚动位置,系统返回则保留
我的应用首页包含顶部大图和底部LazyColumn,点击第4/5个列表项跳转到对应页面后,通过TopAppBar的返回按钮回到首页时,LazyColumn会回到顶部;但用系统导航栏返回时,滚动位置能正常保留。当前返回逻辑是用navController.navigate(Screens.Contents.route),需要修改代码让TopAppBar返回和系统返回效果一致。
问题原因
使用navigate(Screens.Contents.route)跳回首页时,会在导航栈中重新创建一个ContentsScreen实例,导致rememberLazyListState被重新初始化,滚动位置丢失。而系统返回是直接弹出当前页面,首页的实例一直保存在导航栈中,所以滚动状态得以保留。
解决方案
将返回逻辑从navigate改为popBackStack(),该方法会直接从导航栈中移除当前页面,回到上一个页面(首页),不会重新创建首页实例,因此能保留原有的滚动状态。
步骤1:修改子页面的返回逻辑
不再通过回调传递返回方法,直接在子页面中获取导航控制器,调用popBackStack()。
步骤2:更新相关代码文件
修改NavGraph.kt
移除子页面的navigateContentsScreen回调参数:
@Composable fun NavGraph(navController: NavHostController){ NavHost(navController = navController, startDestination = Screens.Contents.route ) { addContentsScreen(navController, this) addScreen1(navController, this) addScreen2(navController, this) addScreen3(navController, this) addScreen4(navController, this) addScreen5(navController, this) } } private fun addContentsScreen( navController: NavHostController, navGraphBuilder: NavGraphBuilder ) { navGraphBuilder.composable(route = Screens.Contents.route) { ContentsScreen( navigateScreen1 = { navController.navigate(Screens.Screens1.route) }, navigateScreen2 = { navController.navigate(Screens.Screens2.route) }, navigateScreen3 = { navController.navigate(Screens.Screens3.route) }, navigateScreen4 = { navController.navigate(Screens.Screens4.route) }, navigateScreen5 = { navController.navigate(Screens.Screens5.route) }, ) } } // 所有子页面的composable不再传递返回回调 private fun addScreen1(navController: NavHostController, navGraphBuilder: NavGraphBuilder) { navGraphBuilder.composable(route = Screens.Screens1.route) { Screen1() } } private fun addScreen2(navController: NavHostController, navGraphBuilder: NavGraphBuilder) { navGraphBuilder.composable(route = Screens.Screens2.route) { Screen2() } } private fun addScreen3(navController: NavHostController, navGraphBuilder: NavGraphBuilder) { navGraphBuilder.composable(route = Screens.Screens3.route) { Screen3() } } private fun addScreen4(navController: NavHostController, navGraphBuilder: NavGraphBuilder) { navGraphBuilder.composable(route = Screens.Screens4.route) { Screen4() } } private fun addScreen5(navController: NavHostController, navGraphBuilder: NavGraphBuilder) { navGraphBuilder.composable(route = Screens.Screens5.route) { Screen5() } }
修改Screen4.kt(Screen1-Screen5都需做相同修改)
通过LocalNavController.current获取导航控制器,返回按钮点击时调用popBackStack():
@OptIn(ExperimentalMaterial3Api::class) @Composable fun Screen4() { val navController = LocalNavController.current val text = "Screen4" Scaffold( containerColor = lightGray, contentColor = darkGrey, topBar = { TopAppBar( modifier = Modifier.height(80.dp), title = { Box( Modifier.fillMaxHeight(), contentAlignment = Alignment.Center ) { Text( maxLines = 1, overflow = TextOverflow.Ellipsis, text = text, color = orange, ) } }, navigationIcon = { Box( Modifier.fillMaxHeight(), contentAlignment = Alignment.Center ) { IconButton( onClick = { navController.popBackStack() } ) { Icon( imageVector = Icons.Filled.ArrowBack, contentDescription = "Back", tint=orange, ) } } }, colors = TopAppBarDefaults.mediumTopAppBarColors( containerColor = darkGrey ) ) } ) { contentPadding -> Column( modifier = Modifier .fillMaxSize() .padding(contentPadding) .verticalScroll(rememberScrollState()), ) { Text( text = "Screen4", color = darkGrey, textAlign = TextAlign.Justify, modifier = Modifier.padding(24.dp) ) } } }
补充说明
如果需要确保精准回到首页(避免栈中有多个首页实例),可以使用带参数的popBackStack:
navController.popBackStack(Screens.Contents.route, inclusive = false)
inclusive = false表示不包含目标页面(即保留首页实例),适合大部分场景。
内容的提问来源于stack exchange,提问作者Alice Magic
相关产品推荐
相关产品推荐

