I am using Navigation Component with Navigation Drawer.
I have added Fragments for each Navigation item in the menu.
Add NavHostFragment where this Fragment will be swapped
Then added Fragments as Destinations
I want master Detail Navigation i.e.
start destination -> fragment 2
back button -> start destination
start destination -> fragment 2 -> fragment 3 -> fragment 4
back button -> start destination
My question is whether I should add any connections to this graph?
I also need to have one menu item which is just logout function call not fragment swapping, so I could not configure it with default setup
val navController = findNavController(R.id.main_nav_host_fragment)
nav_view.setupWithNavController(navController)
But rather have to use
nav_view.setNavigationItemSelectedListener(this)
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
when (item.itemId) {
R.id.navSignOut -> {
loginViewModel.logout()
}
else -> {
val navController = findNavController(R.id.main_nav_host_fragment)
navController.navigate(item.itemId)
}
}
drawer_layout.closeDrawer(GravityCompat.END)
return true
}
I also need to show Login Activity above (modally) the Main App Activity with Navigation Drawer. Can I use Navigation Graph for it and how?
Login Activity should: on back button -> close app, if logged out -> start above main activity, if logged in go to main activity
So I have to questions:
1. Should I use any actions?
2. Should I use custom navigation for drawer or setupWithNavController()?
3. What about modal login activity navigation?
The part I undrestood from your question is how to navigate to logout.
Usually when the user clicks on logout you want to log them out and navigate to a startup screen.
So you need to add your startup activity to nav_graph.
Michael, navigation architecture it is not that easy to understand at the beginning, what you want to is not the exception. But as this navigation is new, I just suggest you to follow the code lab.
https://codelabs.developers.google.com/codelabs/android-navigation/#0
I see for instance your line to close the drawer. The code lab has instructions on how to setup the nav drawer with navigation and the UI
I hope it helps you.
Related
I have a bottom navigation bar which is connected with navHost and is configured using the following code:
Val navHostFragment =supportFragmentManager.findFragmentById(R.id.fragment) as NavHostFragment
val navController = navHostFragment.navController
val bottomNavBar = findViewById<BottomNavigationView>(R.id.bottomBar)
setupWithNavController(bottomNavBar, navController)
I have 4 fragments now when I switch to 2nd fragment(by clicking on 2nd icon in the bottom navigation bar) and then I navigate to another fragment which is linked to the 2nd fragment. When I click on the back button I switch to 2nd fragment.
All good till far.
The problem is: I want to go back to 2nd fragment from the opened fragment when I reselect the same icon in the bottom navigation bar
I solved my issue with the help of this thread. If someone is facing the same issue, check this out:
Android clear backstack after reselecting Bottom Navigation tab
I have integrated a better solution which lets you have animations too when switching from one fragment to another.
val id = navController.currentDestination?.id
when (id) {
R.id.detailedTransactionAnalysis -> {
navController.navigate(R.id.action_detailedTransactionAnalysis_to_MainScreen)
}
R.id.detailedCategoryTransactionsFragment -> {
navController.navigate(R.id.action_detailedCategoryTransactionsFragment_to_MainScreen)
}
R.id.addTransaction -> {
navController.navigate(R.id.action_addTransaction_to_Stats)
}
}
navController.popBackStack(reselectedDestinationId, inclusive = false)
It works totally fine.
Good day. So I've been working around with NavComponent of Jetpack for Android
I've thought that management of BackStack of fragments had to be implemented there already, well in fact it is there but I have faced an issue.
Here is my structure:
I have and entry Activity
I have a NavHost in the activity
I have Bottom Navigation bar in the Activity
For each Bottom Item I am using separate Fragments to navigate through.
Here is the code for the navigation.
bottomNavigationView.setOnNavigationItemSelectedListener {
when (it.itemId) {
R.id.navigation_home -> {
navController.apply {
navigate(R.id.navigation_home)
}
true
}
R.id.navigation_dashboard -> {
navController.apply {
navigate(R.id.dashboardFragment)
}
true
}
R.id.navigation_notifications -> {
true
}
else -> {
false
}
}
}
Never mind the last item.
So the issue is next.
If I try to switch between home and dashboard multiple times, when I press back then the stack surely will start popping all the items included there. So if I move like 6 times it will take me 12 attempts to actually exit the app.
Currently I couldn't find any source where for example the navigate() method will accept some sort of argument to cash my fragments instead of recreating it each time and adding to the BackStack.
So what kind of approach would you suggest?
If I to manage the BackStack manually on each back button pressed, what's the purpose of NavController at all? Just for creating and FORWARD navigation?
I think I'm missing some source in Android's official docs.
Thank you beforehand.
P.S.
using navController.popBackStack() before calling navigate() surely isn't the correct choice.
According to the documentation here :
NavigationUI can also handle bottom navigation. When a user selects a menu item, the NavController calls onNavDestinationSelected() and automatically updates the selected item in the bottom navigation bar.
to do so you have to give your bottom navigation items an ids as same as the corresponding destination in your navigation graph , and then tie you bottom view to the controller like this :
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
NavController navController = navHostFragment.getNavController();
BottomNavigationView bottomNav = findViewById(R.id.bottom_nav);
NavigationUI.setupWithNavController(bottomNav, navController);
Note : from my personal experience , when the startDestination in the graph , that start by default is not currently in back stack (In my case it was the landing page which i pop it out when going to home fragment) then the app act with weird behavior like this . so make sure the start destination is existed in your back stack on should work fine .
I am using Jetpack navigation to navigate between the fragments.Since I am using it for the first time I am unaware about how it will navigate from fragment two to fragment one on click of a button or based on some condition in the application.Please let me know if anyone knows about it
Try these codes:
yourButton.setOnClickListener(){
activity?.onNavigateUp()
}
or
val activity = requireActivity()
yourButton.setOnClickListener(){
if (activity is YourMainActivity) {
activity.onSupportNavigateUp()
//or
activity.onBackPressed()
}
}
I implemented conditional navigation to my LoginFragment, with android navigation architecture component. The problem I facing now, is that I would like to hide the up button on the toolbar, and the disable any in-app navigation while the user is not logged in.
I would like to be able to implement this with a one-activity approach, where the Activity sets up the in app navigation UI and the navController like in the android sunflower demo, and the navigation destinations are Fragments.
I implemented the conditional navigation as discribed here:
Navigation Architecture Component - Login screen
How can I properly implement hiding the navigation and the up button on the login screen, with Navigation Architecture Component?
I don't know exactly what you mean by hiding navigation, but I will assume you mean hiding a drawer layout. To hide the up button and lock the drawer add the following to your MainActivity's onCreate. I'm using Kotlin.
myNavController.addOnDestinationChangedListener { _, destination ->
if (destination.id == R.id.loginFragment) {
myDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
myToolbar.setVisibility(View.GONE)
} else {
myDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
myToolbar.setVisibility(View.VISIBLE)
}
To make just the up button go away use myToolbar.setNavigationIcon(null) and to make it come back use myToolbar.setNavigationIcon(R.id.my_icon)
My method is adding the login page to the root set
val navController = findNavController(R.id.main_nav_host)
val appBarConfiguration = AppBarConfiguration(setOf(R.id.home_dest,
R.id.user_dest,R.id.login_dest))
toolbar.setupWithNavController(navController, appBarConfiguration)
So when you are on the login page, there is no back button.
System back button can override onBackPressed()
override fun onBackPressed() {
if (findNavController(R.id.main_nav_host).currentDestination?.id != R.id.next_dest)
super.onBackPressed()
}
}
Sorry for my English
I have such code setup for navigation architecture component:
val navController = findNavController(R.id.main_nav_host_fragment)
nav_view.setupWithNavController(navController)
bottom_navigation.setupWithNavController(navController)
//nav_view.setNavigationItemSelectedListener(this)
navController.addOnNavigatedListener { controller, destination ->
if(destination.id == R.id.loginActivity) {
Toast.makeText(context, "Log Out navigation destination", Toast.LENGTH_LONG).show()
}
}
And I have found here two issues:
Selecting in Navigation Drawer Menu Item that doesn't appear on Bottom Navigation View causes to select first Menu Item in Bottom Navigation View. Which seems to be incorrect (No Item should be selected there)
OnNavigatedListener is not called when selecting Menu Item in Navigation Drawer that has menu item id set to Activity Destination (precisely action to Activity Destination) - so instead of intercepting this action and log out user, I need to pass stupid default arguments to Activity Destination in Nav Graph to log out user in Login Activity Destination. Do you know why OnNavigatedListener is not called for Activity Destinations, and is only called for Fragment Destinations? Why there is not event listener OnBeginNavigationListener to conditionally prevent navigation or add some side effects?