I have screen like below which contain a navigation drawer and bottom navigation on same screen:
I am using Jetpack Navigation Architecture Component.
Current issue and What I have tried?
Clicking on the 2nd and 3rd bottom nav item shows back arrow on toolbar?
Tried: setting fragments associated with 2nd and 3rd bottom nav to top level destinations
appBarConfig = AppBarConfiguration(setOf(R.layout.fragment_star, R.layout.fragment_stats, R.layout.fragment_user))
instead of
appBarConfig = AppBarConfiguration(navController.graph, drawerLayout)
Did not worked.
Any help highly appreciated!
My code look like below.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <androidx.drawerlayout.widget.DrawerLayout android:id="@+id/drawerLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/> <fragment android:id="@+id/navHostFragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph" /> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottomNav" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:background="?android:attr/windowBackground" app:menu="@menu/menu_bottom" /> </LinearLayout> <!-- gives navDrawer material look--> <com.google.android.material.navigation.NavigationView android:id="@+id/navView" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:menu="@menu/nav_drawer_menu" app:headerLayout="@layout/nav_header" android:fitsSystemWindows="true" /> </androidx.drawerlayout.widget.DrawerLayout> </layout>
menu_bottom.xml
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/starFragment" android:icon="@drawable/ic_star_green_48dp" android:title="@string/bottom_nav_title_star"/> <item android:id="@+id/statsFragment" android:icon="@drawable/ic_stats_green_48dp" android:title="@string/bottom_nav_title_stats"/> <item android:id="@+id/userFragment" android:icon="@drawable/ic_user_green_48dp" android:title="@string/bottom_nav_title_user"/> </menu>
nav_graph.xml
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph_main" app:startDestination="@id/starFragment"> <fragment android:id="@+id/starFragment" android:name="com.example.app.ui.StarrFragment" android:label="Star" tools:layout="@layout/fragment_star"> </fragment> <fragment android:id="@+id/statsFragment" android:name="com.example.app.StatsFragment" android:label="fragment_stats" tools:layout="@layout/fragment_stats" /> <fragment android:id="@+id/userFragment" android:name="com.example.app.UserFragment" android:label="fragment_user" tools:layout="@layout/fragment_user" /> </navigation>
ActivityMain.kt
class MainActivity : AppCompatActivity() { private lateinit var drawerLayout: DrawerLayout private lateinit var appBarConfig: AppBarConfiguration private lateinit var navController: NavController override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main) setSupportActionBar(toolbar) drawerLayout = binding.drawerLayout navController = this.findNavController(R.id.navHostFragment) binding.bottomNav.setupWithNavController(navController) NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout) appBarConfig = AppBarConfiguration(navController.graph, drawerLayout) // lock drawer when not in start destination navController.addOnDestinationChangedListener { nc, nd, _ -> if(nd.id == nc.graph.startDestination){ drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) } else{ drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) } } NavigationUI.setupWithNavController(binding.navView, navController) } override fun onSupportNavigateUp(): Boolean { // replace navigation up button with nav drawer button when on start destination return NavigationUI.navigateUp(navController, appBarConfig) } }
Navigation drawers are the most common use android widget in android. The user can view the navigation drawer when they swipe the activity's screen from the left edge of the android device. A user can also find it from the activity, by tapping the app icon (also known as the “hamburger” menu) in the action bar.
Step 3 -Setup NavigationView NavigationView is an easy way to display a navigation menu from a menu resource. This is most commonly used in conjunction with DrawerLayout to implement Material navigation drawers.
No need of writing separate code to replace the back button with the drawer icon.
In AppBarConfiguration pass the fragment ids (from nav_graph) which you are using to navigate from both bottom navigation & navigation drawer. (P.S fragments and its associated icon should have same ids)
For your case the AppBarConfiguration should look like this :
appBarConfig = AppBarConfiguration.Builder(R.id.starFragment, R.id.statsFragment, R.id.userFragment) .setDrawerLayout(drawerLayout) .build()
Setup the action bar :
setSupportActionBar(toolbar) setupActionBarWithNavController(navController, appBarConfig)
Now setup navcontroller for both bottom navigation & navigation view :
navView.setupWithNavController(navController) bottomNav.setupWithNavController(navController)
onSupportNavigateUp function should should be :
override fun onSupportNavigateUp(): Boolean { return navController.navigateUp(appBarConfig) }
Back button press should be handled if drawer is open :
override fun onBackPressed() { if (drawerLayout.isDrawerOpen(GravityCompat.START)) { drawerLayout.closeDrawer(GravityCompat.START) } else { super.onBackPressed() } }
Bonus
By default when you click bottom navigation icon in the order icon_1 then icon_2 then icon_3 and from there you press back button it will navigate back to home icon that's icon_1
If you want to navigate back in the reverse order in which you have clicked the icons (back stack manner) then add android:menuCategory="secondary" to the item in the menu. So your menu will be like :
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/starFragment" android:icon="@drawable/ic_star_green_48dp" android:title="@string/bottom_nav_title_star" android:menuCategory="secondary"/> <item android:id="@+id/statsFragment" android:icon="@drawable/ic_stats_green_48dp" android:title="@string/bottom_nav_title_stats" android:menuCategory="secondary"/> <item android:id="@+id/userFragment" android:icon="@drawable/ic_user_green_48dp" android:title="@string/bottom_nav_title_user" android:menuCategory="secondary"/> </menu>
Hope the back button icon will be solved now :)
This project uses DrawerLayout and simulates BottomNavigationView using RadioButtons, this is the way I found to solve the problem
In the Google Codelab navigation project they do what Adithya T Raj mention but it only serves to show the DrawerLayout on landscape and BottomNavigationView on Portrait. The project link:
I try to force them to show me both on this branch but only the DrawerLayout is shown
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With