Reputation: 812
I finally started using Compose for Android and I am currently stuck at navigation. I have two questions:
1. I have implemented a bottom navigation with three buttons and one of the buttons triggeres a nested navigation graph, like:
HOME --- CONTACTS --- FAVOURITES
|
DETAILS
So when I open details screen from home and switch tabs, the behavior is correct, the state and last destination in the nested graph is memorized and when I tap again on home, it keeps the state and switches back to details. However, if I am on any of the other tabs and press back, it brings me to home but it resets the state, it doesn't bring me back into details. How can I achieve that?
Navigation Bar:
@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)
},
)
}
}
Navigation Host:
@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()
}
}
}
Nested Home Navigation Graph:
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. When I am back in home with the entire navigation stack clear and press back once more, naturally the app closes. How can I intercept back press and implement a "tap again to exit" confirmation feature at that point?
Upvotes: 8
Views: 4473
Reputation: 10375
I resolved the problem using an empty BackHandler
. As your Contacts and Favorites screens do not have any nested navigation themselves, this should work in your case. The BackHandler
will consume the back press and will prevent it from being interpreted as popBackStack
.
@Composable
fun Contacts() {
val context = LocalContext.current
BackHandler {
// leave empty
}
}
In the BackHandler
, you also could place a "click twice to close app" behavior. You can try it like this:
@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
}
}
}
}
Upvotes: 1
Reputation: 10977
I cannot answer your first question, but for your second one: I just stumbled upon BackHandler. I just tried it real quick and it got called instead of closing the app, so that should solve your issue.
Upvotes: 1