Pressing a button to navigate to another screen throws java.
2024-04-17 13:45

I made an app for learning about Bottom Bar Navigation with Android Jetpack Compose and then decided extend it. Added LoginScreen.

In MainActivity I call function MainScreen.

@Composable fun MainScreen() { val navController = rememberNavController() var showTopBar by rememberSaveable { mutableStateOf(true) } // to hide top bar in login screen var showBottomBar by rememberSaveable { mutableStateOf(true) } // to hide bottom bar in login screen val navBackStackEntry by navController.currentBackStackEntryAsState() showTopBar = when (navBackStackEntry?.destination?.route) { "login" -> false else -> true } showBottomBar = when (navBackStackEntry?.destination?.route) { "login" -> false else -> true } Scaffold( topBar = { if (showTopBar) MyTopAppBar() }, bottomBar = { if (showBottomBar) BottomNavigationBar(navController) }, content = { Box(modifier = Modifier.padding(it)) { Navigation(navController = navController) } } ) }

This is Navigation function.

@Composable fun Navigation(navController: NavHostController) { NavHost(navController = navController, startDestination = NavigationItem.Login.route) { composable(NavigationItem.Lessons.route) { LessonsScreen() } composable(NavigationItem.Practice.route) { PracticeScreen() } composable(NavigationItem.Profile.route) { ProfileScreen() } composable(NavigationItem.Login.route) { LoginScreen() } } }

Function for bottom navigation bar.

@Composable fun BottomNavigationBar(navController: NavController) { val items = listOf( NavigationItem.Lessons, NavigationItem.Practice, NavigationItem.Profile ) NavigationBar { val navBackStackEntry by navController.currentBackStackEntryAsState() val currentRoute = navBackStackEntry?.destination?.route items.forEach { item -> NavigationBarItem( label = { Text(item.title) }, icon = { Icon( painter = painterResource(item.icon), contentDescription = item.title, modifier = Modifier.size(25.dp) ) }, selected = currentRoute == item.route, onClick = { navController.navigate(item.route) { navController.graph.startDestinationRoute?.let { route -> popUpTo(route) { saveState = true } } launchSingleTop = true restoreState = true } }, ) } } }

Class NavigationItem for screens as objects. Initially it was supposed for BottomNavigationBar only. Then I added object Login.

sealed class NavigationItem( var route: String, var icon: Int, var title: String ) { object Lessons : NavigationItem( route = "lessons", icon = R.drawable.book, title = "Lessons" ) object Practice : NavigationItem( route = "practice", icon = R.drawable.practice, title = "Practice" ) object Profile : NavigationItem( route = "profile", icon = R.drawable.user, title = "Profile" ) object Login : NavigationItem( route = "login", icon = R.drawable.book, // can't pass null title = "Login" ) }

And function LoginSection - part of LoginScreen

@Composable private fun LoginSection() { val navController = rememberNavController() LoginTextField( label = "Email", trailing = "", modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(MaterialTheme.dimens.small2)) LoginTextField( label = "Password", trailing = "Forgot?", modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(MaterialTheme.dimens.small3)) Button( modifier = Modifier .fillMaxWidth() .height(MaterialTheme.dimens.buttonHeight), onClick = { // problem here navController.navigate(NavigationItem.Lessons.route) }, colors = ButtonDefaults.buttonColors( containerColor = if (isSystemInDarkTheme()) BlueGray else Black, contentColor = Color.White ), shape = RoundedCornerShape(size = 4.dp) ) { Text( text = "Log in", style = MaterialTheme.typography.labelMedium.copy(fontWeight = FontWeight.Medium) ) } }

When I press the button "Log in" I get that:

java.lang.IllegalArgumentException: Cannot navigate to NavDeepLinkRequest{ uri=android-app://androidx.navigation/lessons }. Navigation graph has not been set for NavController androidx.navigation.NavHostController@e54b35e.

I know I have to change the code if I want to add more screens and functionality but I can't see where exactly is the problem now. Appreciate your help.



Answer 1 :

Problem is in the composable function you didn't pass the navController inside of LoginScreen()

@Composable fun Navigation(navController: NavHostController) { NavHost(navController = navController, startDestination = NavigationItem.Login.route) { composable(NavigationItem.Lessons.route) { LessonsScreen() } composable(NavigationItem.Practice.route) { PracticeScreen() } composable(NavigationItem.Profile.route) { ProfileScreen() } composable(NavigationItem.Login.route) { LoginScreen() } }

solution is

@Composable fun Navigation(navController: NavHostController) { NavHost(navController = navController, startDestination = NavigationItem.Login.route) { composable(NavigationItem.Lessons.route) { LessonsScreen() } composable(NavigationItem.Practice.route) { PracticeScreen() } composable(NavigationItem.Profile.route) { ProfileScreen() } composable(NavigationItem.Login.route) { // pass the same instance of navcontroller , // dont create new instance constructor params LoginScreen(navController) } }
other answer :

It seems like youre encountering an issue when navigating to another screen using Jetpack Compose and Androids Navigation component. The error message you provided indicates that theres an issue with navigating to a deep link request.

The java.lang.IllegalArgumentException: Cannot navigate to NavDeepLinkRequest error often occurs when theres a problem with how youre navigating to a destination. This could be due to various reasons such as incorrect route setup, missing destinations, or incorrect navigation actions.

Here are a few things you can check to resolve this issue:

Check Navigation Graph Setup: Ensure that your navigation graph (nav_graph.xml file) is correctly set up with all the destinations (Lessons, Practice, Profile, Login) and their corresponding actions.

Verify Destination Routes: Double-check that the routes used in your NavHost and BottomNavigationBar match the routes defined in your navigation graph.

Check NavHostController Usage: Ensure that you are using the correct NavHostController instance throughout your navigation. In your case, youre passing NavHostController to Navigation composable and NavController to BottomNavigationBar. Make sure they are consistent and correctly initialized.

Ensure Deep Linking is Set Up Correctly: If youre using deep links, ensure that they are configured properly in your navigation graph and that any associated deep link data is correctly handled.

Verify Navigation Actions: If youre using actions to navigate between destinations, ensure that the actions are correctly set up in your navigation graph and that youre using them properly in your code.

By reviewing these aspects of your navigation setup, you should be able to identify and resolve the issue causing the IllegalArgumentException. If the issue persists, providing more details about your navigation graph setup and any specific actions triggering the error would be helpful for further troubleshooting.