我终于开始使用 Android 版 Compose,但目前陷入导航困境。我有两个问题:
1. 我已经实现了带有三个按钮的底部导航,其中一个按钮触发嵌套导航图,例如:
HOME --- CONTACTS --- FAVOURITES
|
DETAILS
因此,当我从主页打开详细信息屏幕并切换选项卡时,行为是正确的,嵌套图中的状态和最后目的地会被记住,当我再次点击主页时,它会保留状态并切换回详细信息。但是,如果我在任何其他选项卡上并按返回,它会将我带回到主页,但会重置状态,不会让我返回详细信息。我怎样才能实现这一目标?
导航栏:
@Composable
fun BottomNavigationBar(navController: NavHostController) {
BottomNavigation {
val backStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = backStackEntry?.destination?.route
BottomNavigationCollection.items.forEach { navItem ->
BottomNavigationItem(
selected = currentRoute == navItem.route,
onClick = {
navController.navigate(navItem.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
icon = {
Icon(
imageVector = navItem.icon,
contentDescription = navItem.title
)
},
label = {
Text(text = navItem.title)
},
)
}
}
导航主机:
@Composable
fun NavigationHost(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = NavigationRoutes.Home.route,
route = "root"
) {
homeGraph(navController)
composable(NavigationRoutes.Contacts.route) {
ContactsScreen()
}
composable(NavigationRoutes.Favorites.route) {
FavouritesScreen()
}
}
}
嵌套主页导航图:
fun NavGraphBuilder.homeGraph(navController: NavController) {
navigation(
startDestination = NavigationRoutes.Dashboard.route,
route = NavigationRoutes.Home.route
) {
composable(NavigationRoutes.Dashboard.route) {
DashboardScreen(navController)
}
composable(NavigationRoutes.Details.route) {
DetailsScreen(navController)
}
}
}
2. 当我回到家里,整个导航堆栈都清晰并再次按回时,应用程序自然会关闭。我怎样才能拦截后按并在此时实现“再次点击退出”确认功能?
我无法回答你的第一个问题,但对于你的第二个问题:我刚刚偶然发现了BackHandler。我只是快速尝试了一下,它被调用而不是关闭应用程序,所以这应该可以解决您的问题。
BackHandler
解决了问题。由于您的“联系人”和“收藏夹”屏幕本身没有任何嵌套导航,因此这应该适合您的情况。 BackHandler
将消耗后推力并防止其被解释为 popBackStack
。
@Composable
fun Contacts() {
val context = LocalContext.current
BackHandler {
// leave empty
}
}
在
BackHandler
中,您还可以放置“单击两次以关闭应用程序”行为。你可以这样尝试:
@Composable
fun Contacts() {
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
var firstPressed by remember { mutableStateOf(false) }
BackHandler() {
if (firstPressed) {
val activity = (context as? Activity)
activity?.finish()
} else {
firstPressed = true
Toast.makeText(context, "Press back again to exit", Toast.LENGTH_SHORT).show()
coroutineScope.launch {
delay(2000L) // set delay here as wished
firstPressed = false
}
}
}
}