I am trying to create a new activity with drawer layout. To do this, I used Android Studio's default code generator: File -> New -> Activity -> Navigation Drawer Activity. It created a bunch of files with fragments, drawer, and (jetpack) navigation support and their corresponding resources such as navigation file and layout files. I tried to run the new activity and it installed successfully. The problem is, my navigation drawer is not working. The menu items in my drawer do not trigger any change in host navigation fragment.
I've been stuck for a day already and have tried many solutions already and still, my menu items won't let me navigate to another destination.
Here is my resulting MainActivity.java:
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
private ActivityMainBinding binding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.appBarMain.toolbar);
DrawerLayout drawer = binding.drawerLayout;
NavigationView navigationView = binding.navView;
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
.setOpenableLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
return NavigationUI.onNavDestinationSelected(
item,
Navigation.findNavController(this, R.id.nav_host_fragment_content_main)) ||
super.onOptionsItemSelected(item);
}
}
The overridden onOptionsItemSelected() function is from Android's codelab.
Here is my navigation file:
<?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/mobile_navigation"
app:startDestination="#+id/nav_home">
<fragment
android:id="#+id/nav_home"
android:name="com.bicolexpress.delivery.ui.main.ui.home.HomeFragment"
android:label="#string/menu_home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/nav_gallery"
android:name="com.bicolexpress.delivery.ui.main.ui.gallery.GalleryFragment"
android:label="#string/menu_gallery"
tools:layout="#layout/fragment_gallery" />
<fragment
android:id="#+id/nav_slideshow"
android:name="com.bicolexpress.delivery.ui.main.ui.slideshow.SlideshowFragment"
android:label="#string/menu_slideshow"
tools:layout="#layout/fragment_slideshow" />
</navigation>
Based on the codelab link above:
If NavigationUI finds a menu item with the same ID as a destination on
the current graph, it configures the menu item to navigate to that
destination.
This is true for the generated menu items and destination IDs. But still, does not work. Can anyone point me to what I missed? I desperately need your help.
Android Studio Version: Electric Eel | 2022.1.1
So I tried to copy the layout from codelab. And guess what, the click listeners worked!
I noticed that in codelab's layout, the NavigationView was added into the DrawerLayout as the last child. So I modified my activity_main.xml to:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
android:id="#+id/app_bar_main"
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
Related
I'm having the problem that when I navigate back from a fragment, it doesn't take me back to the previously selected fragment in my BottomNavigation.
I have a single MainActivity that has both a DrawerLayout and a BottomNavigation. The BottomNavigation has 3 items in it corresponding to 3 fragments (Home, Readings, Graph). All 3 are top-level destinations in the app (all 3 have the hamburger menu icon). The DrawerLayout has 1 item in it which opens my AboutFragment.
From the Readings page in the Bottom Navigation, I open the Drawer Layout and click About which opens the AboutFragment. When I then click the 'up' arrow in the AboutFragment it doesn't take me back to Readings, instead it takes me back to Home (the first item in the Bottom Navigation). How can I make it go back to Readings which was the page I was previously on?
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(mBinding.getRoot());
setSupportActionBar(mBinding.appBarMain.mainToolbar);
mBottomNav = mBinding.appBarMain.mainBottomBar;
mDrawerLayout = mBinding.drawerLayout;
NavigationView navigationView = mBinding.navView;
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.home, R.id.readings, R.id.graph)
.setOpenableLayout(mDrawerLayout)
.build();
NavController navController = Navigation.findNavController(this, R.id.main_fragments_container);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
NavigationUI.setupWithNavController(mBottomNav, navController);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
NavController navController = Navigation.findNavController(this, R.id.main_fragments_container);
return NavigationUI.onNavDestinationSelected(item, navController)
|| super.onOptionsItemSelected(item);
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.main_fragments_container);
return NavigationUI.navigateUp(navController, mAppBarConfiguration) || super.onSupportNavigateUp();
}
}
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"
app:startDestination="#+id/home">
<fragment
android:id="#+id/home"
android:name="com.myapp.ui.tabs.HomeFragment"
android:label="#string/menu_title_home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/readings"
android:name="com.myapp.ui.tabs.ReadingsFragment"
android:label="#string/menu_title_readings"
tools:layout="#layout/fragment_readings" />
<fragment
android:id="#+id/graph"
android:name="com.myapp.ui.tabs.GraphFragment"
android:label="#string/menu_title_graph"
tools:layout="#layout/fragment_graph" />
<fragment
android:id="#+id/about"
android:name="com.myapp.ui.about.AboutFragment"
android:label="#string/general_about"
tools:layout="#layout/fragment_about" />
</navigation>
NOTE
As a test, if I make the FAB button (visible on all BottomNavigation fragment screens) go to AboutFragment, then when I click 'up' arrow in the AboutFragment it DOES take me back to Readings. It seems that accessing AboutFragment via the DrawerLayout acts differently to accessing AboutFragment from the FAB.
Can you try to:
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.mainNavHostFragment)
return when(navController.currentDestination?.id) {
R.id.about-> {
navController.popBackStack()
true
}
else -> navController.navigateUp()
}
}
Let me know if it works for you
Answering my own question here for anyone else who has this problem. Solution is to put android:menuCategory="secondary" in the AboutFragment item in the DrawerLayout menu file.
menu_drawer.xml
<item
android:id="#+id/nav_about"
android:menuCategory="secondary"
android:icon="#drawable/vic_about"
android:title="#string/general_about" />
Reason this works is:
By default, the back stack will be popped back to the navigation graph's start destination. Menu items that have android:menuCategory="secondary" will not pop the back stack.
I found the solution in this post https://stackoverflow.com/a/60516769/728002
I have a basic app, containing a drawer layout. Each option in the drawer opens up a new fragment page for the user to view. Here is the drawer layout code.
<androidx.drawerlayout.widget.DrawerLayout
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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
Here is the app_bar_main.xml code.
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DashBoardActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And here is the content_main.xml. And also the main activity DashBoardActivity.kt
class DashBoardActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dashboard)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.nav_company_emissions, R.id.nav_your_emissions, R.id.nav_contact,
R.id.nav_privacy_policy
), drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
From my understanding when you click a button in the drawer layout the fragment in the host fragment is replaced with the relevant clicked on fragment.
My questions is... How do I programatically put another fragment in this nav host view which hasn't been set up with the drawer layout. My problem is one of the fragments contains a profile for a user with an edit button. I want to open a new fragment when the edit button is clicked and wish for the user to still have access to the drawer when they do so don't want to go to another activity.
In my mind I just want to replace the profile_fragment with the edit_fragment. But when I've tried something like this below its placed the fragment onto of the profile one so that you have this weird looking screen with two fragments on top of one another.
val frag: Fragment = EditYourEmissionsFragment()
val fragMan:FragmentManager = activity!!.supportFragmentManager
val fragTran: FragmentTransaction = fragMan.beginTransaction()
fragTran.add(R.id.nav_host_fragment, frag)
fragTran.addToBackStack(null)
fragTran.commit()
I'm still a relative novice when it comes to Android and Kotlin so am struggling to understand how I would go about doing my user case.
Scenario for trying to help paint a picture of what I want to happen:
User loads app and lands on home_fragment.
Opens drawer menu, clicks profile_fragment.
Once in profile_fragment opens the user presses edit.
A new fragment takes over the screen, but retains the ability to open the menu drawer.
User can now either open the drawer menu and navigate to other places across the app. Or save their profile and get taken back to the profile_fragment.
Thank you in advance for any help. Apologies if its not particularly clear.
include the EditYourEmissionsFragment in the navigationGraph like this:
<fragment
android:id="#+id/EditYourEmissionsFragment"
android:name="com.example.application.EditYourEmissionsFragment"
android:label="Edit Profile"
tools:layout="#layout/fragment_edit_omissions"/>
and then on your ProfileFragment set the onClick to open the destination like this;
val navController = Navigation.findNavController(view)
navController.navigate(R.id.EditYourEmissionsFragment)
and in your MainActivity
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.my_nav_host)
return navController.navigateUp(myAppBarConfiguration) || super.onSupportNavigateUp()
}
My menu was opening from left to right, but I want it to be opened from right to left. I have arranged the code to be opened from right to left, but now the code does not work I get the following error.
java.lang.IllegalArgumentException: No drawer view found with gravity LEFT
I get an error on this line : return NavigationUI.navigateUp(navController, mAppBarConfiguration)
MAİN CLASS
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
NavigationView navigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_sss, R.id.nav_gelisim,
R.id.nav_destek,R.id.nav_hakkımızda,R.id.nav_instagram)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
}
XML
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layoutDirection="rtl"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:itemTextColor="#color/white"
app:itemTextAppearance="#style/NavDrawerTextStyle"
android:layout_gravity="right"
android:theme="#style/NavigationView"
android:background="#color/NavItem"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main2"
app:menu="#menu/activity_main_drawer"/>
</androidx.drawerlayout.widget.DrawerLayout>
You need to handle navigation click on Toolbar like below:
ViewCompat.setLayoutDirection(toolbar, ViewCompat.LAYOUT_DIRECTION_RTL);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (drawer.isDrawerOpen(GravityCompat.END))
drawer.closeDrawer(GravityCompat.END);
else
drawer.openDrawer(GravityCompat.END);
}
});
Also don't forgot to close drawer whenever needed like below:
drawer.closeDrawer(GravityCompat.END)
You could possible find your answer here in this previous post:
Android DrawerLayout - No drawer view found with gravity
You have to set layout Direction in Your Root Drawer Layout
android:layoutDirection="rtl"
If you set the layout direction of the root drawer as follows:
android:layoutDirection="rtl"
All elements will change direction. To solve this, place all elements within a LinearLayout and set LinearLayout direction to ltr.
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
**android:layoutDirection="rtl"**
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
**android:layoutDirection="ltr"**>
<!--place your layout here-->
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:layoutDirection="rtl"
app:menu="#menu/drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>
If you are using the navigation component use the below code in your activity class.
override fun onCreate(savedInstanceState: Bundle?) {
//...
val navHostFragment = supportFragmentManager.findFragmentById(
R.id.my_nav_host_fragment
) as NavHostFragment
navController = navHostFragment.navController
binding.navigationView.setupWithNavController(navController)
//...
}
override fun onSupportNavigateUp(): Boolean {
return NavigationUI.navigateUp(navController, binding.drawerLayout)
}
override fun onBackPressed() {
if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
binding.drawerLayout.closeDrawer(GravityCompat.START)
} else {
super.onBackPressed()
}
}
It seems like the DrawerLayout need to be in the start direction every time,
if you want it to open from the left you need to do the following:
make your DrawerLayout android:layoutDirection="ltr"
remove tools:openDrawer from your DrawerLayout XML
put your NaviagtionView android:layout_gravity="start"
if you want your content to be RTL don't forget to do this in your contentView container android:layoutDirection="rtl"
and it will work like a charm!
Hi I'm trying to use new arch components in my project. Short description what I want to achieve:
When user is on MainFragment I want to display navigation icon (Hamburger) on BottomAppBar. User is able to click navigation icon and display BottomNavigationDrawer
When user select some menu item, or click something on MainFragment he is moved to another fragment, let say DebtDetailsFragment. Then Hamburger should be replaced with 'Back arrow' by NavigationController
Below I pasted my MainActivity code. When I comment line with navigation controller, the Hamburger icon is visible and BottomNavigationDrawer is able to display.
But when I uncomment this line, the Hamburger disappear because NavigationController knows nothing about NavigationView used in BottomNavigationDrawer. I don't use DrawerLayout, so controller thinks Hamburger is not needed.
Method setupWithNavController can control Hamburger icon and back arrow, but I have to provide DrawerLayout as parameter which I don't use.
Documentation for this method:
The Toolbar will also display the Up button when you are on a non-root destination and the drawer icon when on the root destination, automatically animating between them. This method will call [DrawerLayout.navigateUp] when the navigation icon is clicked.
So the question is, how to display Hamburger icon when NavigationController is connected with BottomAppBar but without DrawerLayout? I will handle hamburger click myself in onOptionsItemSelected method.
class MainActivity : BaseActivity() {
#Inject
lateinit var viewModelProvider: ViewModelProvider.Factory
private val viewModel: MainActivityViewModel by lazy {
ViewModelProviders.of(this, viewModelProvider).get(MainActivityViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(bottomAppBar)
val navController = findNavController(R.id.main_nav_host_fragment)
//bottomAppBar.setupWithNavController(navController)
onDestroyDisposables += viewModel.uiStateObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(::render, Timber::e)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.bottomappbar_menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
android.R.id.home -> {
val bottomNavDrawerFragment = BottomNavigationDrawerFragment()
bottomNavDrawerFragment.show(supportFragmentManager, bottomNavDrawerFragment.tag)
}
}
return super.onOptionsItemSelected(item)
}
override fun onSupportNavigateUp(): Boolean {
return findNavController(R.id.main_nav_host_fragment).navigateUp()
}
}
Without setted Navigation controller:
BottomNavigationDrawer
With setted NavigationController - Hamburger invisible.
The BottomAppBar should never display an Up button as per the anatomy of the BottomAppBar - it should only ever display the drawer icon. As seen in the behavior documentation, the Up button should be displayed in a top Toolbar.
Therefore, you should never be calling bottomAppBar.setupWithNavController(navController), but instead calling setupWithNavController(navController) using whatever top Toolbar you have.
To set up your BottomAppBar, you should instead set your own drawer icon and handle clicks on the drawer icon yourself.
The DrawerArrowDrawable class is available to give you a correct drawer icon:
val icon = DrawerArrowDrawable(bottomAppBar.context)
bottomAppBar.navigationIcon = icon
I implemented the BottomAppBar with Jetpack navigation drawer component as following way in my app.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomAppBar bottomAppBar = findViewById(R.id.bottomAppBar);
setSupportActionBar(bottomAppBar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
NavigationView navigationView = findViewById(R.id.nav_view);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupWithNavController(navigationView, navController);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
return NavigationUI.navigateUp(navController, drawer)
|| super.onSupportNavigateUp();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
app_bar_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<include layout="#layout/content_main" />
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bottomAppBar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_gravity="bottom"
app:fabCradleVerticalOffset="16dp"
app:navigationIcon="#drawable/ic_baseline_menu_24"
app:navigationContentDescription="#string/nav_header_desc"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
style="#style/Widget.MaterialComponents.BottomAppBar.Colored"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_menu_send"
app:layout_anchor="#id/bottomAppBar"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
The result will be like this
I have implemented a navigationview in my app , which was automatically created by AndroidStudio. I picked up the NavigationDrawer Activity when I created a new project and the menu items seem ok , but nothing happend when I click on any of the menu item .
Below is my onNavigationItemSelected() method:
#Override
public boolean onNavigationItemSelected(MenuItem item) {
Toast.makeText(MainActivity.this,"onNavigationItemSelected",Toast.LENGTH_LONG).show();
// Handle navigation view item clicks here.
item.setChecked(true);
int id = item.getItemId();
if (id == R.id.medicalRecord) {
Toast.makeText(MainActivity.this,id,Toast.LENGTH_LONG).show();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
And my onCreate method , I create the NavigationView in it
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.linear_layout);
if (babyImage.exists()) {
Drawable drawable = Drawable.createFromPath(Environment.getExternalStorageDirectory() + "/babycare/temp.jpg");
linearLayout.setBackground(drawable);
}
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerLayout.openDrawer(Gravity.LEFT);
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
Of course , I implemented the NavigationView.OnNavigationItemSelectedListener for my class .
I am wondering whether this NavigationView should be implement in Material Design theme or not . Now the theme used in my app is #style/AppTheme
Please , someone help me out , thank you
I solved my question , just simply change the order in my activity_main.xml .
I have a LinearLayout viewgroup and NavigationView in my DrawerLayout viewgroup , at first the NavigationView is the first in my viewgroup and now I change the order , the first one is the LinearLayout and the second is NavigationView , and it work as it suppose to be . Dear!!!
But can someone tell me why it happend ? Does it matter the view order in a viewgroup regardless the display sequence .
I too had this issue and I finally figured out what was wrong, I initially created a sample project with navigation drawer and the main activity xml was as below,
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
But in the actual app I made I did a mistake like this,
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
<LinearLayout...../>
</android.support.v4.widget.DrawerLayout>
I had a LinearLayout below the NavigationView which was the issue.
Then I did this, everything started to work fine.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<LinearLayout...../>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>
Key was to put the NavigationView at last. Weird that UI was not disturbed but callback was.
The Navigation Drawer help say this:
The main content view (the FrameLayout above) must be the first child in the DrawerLayout because the XML order implies z-ordering and the drawer must be on top of the content.
regards to this example:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
So this is the explanation, what is kind of annoying is if you have the wrong layout order as a result of an auto-generated template. I have faced this kind of "problems" with Android Studio a few times and is so fustrating.
I've just had this problem but none of the answers help me. But finally I solved.
In my case, the listener wasn't called because I used in my activity:
NavigationUI.setupWithNavController(navigationView, navController);
That overrides my OnNavigationItemSelectedListener, so I removed that line and I've setted my listener as the following:
final NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(new
NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
FragmentManager fm = getSupportFragmentManager();
fm.popBackStackImmediate();
boolean handled = NavigationUI.onNavDestinationSelected(item, navController);
if (handled) {
ViewParent parent = navigationView.getParent();
if (parent instanceof DrawerLayout) {
((DrawerLayout) parent).closeDrawer(navigationView);
}
}
return handled;
}
});
Here's a piece of NavigationUI that override my listener:
public static void setupWithNavController(#NonNull final NavigationView navigationView,
#NonNull final NavController navController) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
boolean handled = onNavDestinationSelected(item, navController);
//******* CUTTED ***************
return handled;
}
});
}
I hope it can helps.
The Navigation Drawer help say this:
The main content view (the FrameLayout above) must be the first child in the DrawerLayout because the XML order implies z-ordering and the drawer must be on top of the content.
regards to this example:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
What is kind of annoying is if you have the wrong layout order as a result of an auto-generated template. I have faced this kind of "problems" with Android Studio a few times and is so fustrating.
you should change the place of tags. shouldn't do NavigationView first. it works.