7

I created a new navigation drawer activity from Android Studio 3.5 templates, but menu items are not clickable even though I'm listening for NavigationItemSelected.

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

    private AppBarConfiguration mAppBarConfiguration;

    @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);
        navigationView.setNavigationItemSelectedListener(this);

        // 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,
                R.id.nav_tools, R.id.nav_share, R.id.nav_send)
                .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) {
        // 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);
        return NavigationUI.navigateUp(navController, mAppBarConfiguration)
                || super.onSupportNavigateUp();
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        Toast.makeText(this, menuItem.getTitle(), Toast.LENGTH_SHORT).show();
        return true;
    }
}

When I click an item from the drawer, the drawer just closes instead of displaying the Toast in defined in the onNavigationItemSelected method.

Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
hama Mk
  • 127
  • 3
  • 8
  • 1
    Please [edit] your question to provide the layout XML that has the ``. – Mike M. Aug 29 '19 at 03:39
  • This is still a problem in Android Studio 4.0.1 stable version...(are you listening, Google?)...the accepted answer to the questions fixes this. – zaifrun Sep 16 '20 at 12:21
  • Would be nice if anyone using 4.1 (currently not stable version) or 4.2 betas could comment if it has been fixed in those versions? – zaifrun Sep 16 '20 at 12:32
  • 1
    So - still a problem in Android Studio 4.1 stable version that was just released.....should have been fixed by Google. The accepted solution here is still needed. – zaifrun Oct 13 '20 at 11:43
  • So finally seems to be fixed in Android Studio 4.1.2, where the order in the xml file is correct. – zaifrun Jan 27 '21 at 10:22

5 Answers5

19

this problem is caused by the ordering issue of xml file from main content

the default order:

<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" />

<include
    layout="@layout/app_bar_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

change to following order:

<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" />
Borden Chen
  • 306
  • 1
  • 5
  • 3
    For those wondering why this is the correct answer, it is to do with Z order, the NavigationView must be on top of the other controls to receive input. Controls in the XML layout file are ordered bottom -> top, therefore to be the top most control, it must be declared last. – BitByteDog Dec 09 '19 at 00:48
  • @BitByteDog Thanks a lot for your explanation about the Z order of XML layout. I'm also confused about why changing order can make such effect. – Borden Chen Dec 10 '19 at 09:43
  • The Android documentation for [DrawerLayout](https://developer.android.com/reference/android/support/v4/widget/DrawerLayout) is specific, the content view must be placed first, the NavigationView is second. The ordering matters. There are several other container views where ordering matters, for example [FrameLayout](https://developer.android.com/reference/android/widget/FrameLayout.html). Just check the documentation for each control to see if the order of views is significant . – BitByteDog Dec 10 '19 at 18:20
  • Good job, Google. – Divins Mathew Aug 28 '20 at 06:38
2

When you call NavigationUI.setupWithNavController(navigationView, navController), you're saying that you want NavController to handle click events from your NavigationView, navigating to the related screen as per the NavigationUI documentation. This, by necessity, calls setNavigationItemSelectedListener() internally, overriding the setNavigationItemSelectedListener() you call earlier in onCreate(). If you've hooked up your NavigationView to fragments in your app (as the template does out of the box), then there is no need to call setNavigationItemSelectedListener yourself.

Of course, you should ensure that your layout has not changed from what the Navigation Drawer Activity gives you by default - there is a known issue with Android Studio 3.5 that can lead to the order of views being changed which would break cases like DrawerLayout (where the order of children matters greatly)

ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
  • So, it should still be calling `onNavigationItemSelected()`, right? I would assume they've added the `setNavigationItemSelectedListener()` call in an effort to debug. – Mike M. Aug 29 '19 at 03:56
  • @MikeM. - NavigationView only allows one listener set at a time - since NavigationUI is set last, its internal listener is called. – ianhanniballake Aug 29 '19 at 03:58
  • Oop, never mind. I confused that with something else (that's not there; I'm not familiar with Navigation yet). My bad. Anyway, I'll still bet it's a debug attempt after it didn't work out of the box. – Mike M. Aug 29 '19 at 04:02
  • Hi all guys, I'm having the same problem with same Android Studio version: when i click on any entry of the drawer, it just closes and doesn't navigate to the new fragment. How did you solve the problem? – MatteoBelfiori Aug 29 '19 at 08:57
  • 2
    @MatteoBelfiori If yours is the same issue I've been seeing, [this issue in the 3.5 upgrade](https://stackoverflow.com/q/57591080) is causing XML to be improperly reordered, and it's moving the `` to above (and therefore, behind) the main content in the ``. You'll need to move the `` to after the `` (or whatever else you might have for the main content). Then follow the steps in the accepted answer on that linked post, so it doesn't happen again when reformatting/refactoring later. – Mike M. Aug 29 '19 at 09:17
  • 1
    @MikeM.Oh man, thank you so much. Now it works, just by moving the NavigationView as you said. Thank you very much!! – MatteoBelfiori Aug 29 '19 at 09:29
  • Ian, if this ends up being the OP's original issue here, as I suspect, would you please amend your answer to address that, so I can use this as a dupe target in the future? Thanks. – Mike M. Aug 29 '19 at 11:41
  • @MikeM. - I've added a note to my answer. – ianhanniballake Aug 29 '19 at 22:41
  • Oh yes finally, it works thanks a lot guys. It was an issue with the reordering of the views like you said. – hama Mk Aug 30 '19 at 05:31
  • If this helped answer your question, consider accepting the answer to remove this question from the list of unanswered questions. – ianhanniballake Aug 30 '19 at 05:43
1

Inside XML the tag <androidx.drawerlayout.widget.DrawerLayout> in the activity Rearrangement first and <com.google.android.material.navigation.NavigationView> Second . Inside java onCreate example :

navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(@NonNull NavController controller,
                                             @NonNull NavDestination destination, @Nullable Bundle arguments) {
                if(destination.getId() == R.id.nav_home) {
                    Toast.makeText(Permissions_Display.this,"home",Toast.LENGTH_LONG).show();
                } if(destination.getId() == R.id.nav_gallery) {
                    Toast.makeText(Permissions_Display.this,"nav_gallery",Toast.LENGTH_LONG).show();
                }
                if(destination.getId() == R.id.nav_slideshow) {
                    Toast.makeText(Permissions_Display.this,"nav_slideshow",Toast.LENGTH_LONG).show();
                } if(destination.getId() == R.id.nav_tools) {
                    Toast.makeText(Permissions_Display.this,"nav_tools",Toast.LENGTH_LONG).show();
                }
                if(destination.getId() == R.id.nav_share) {
                    Toast.makeText(Permissions_Display.this,"nav_share",Toast.LENGTH_LONG).show();
                } if(destination.getId() == R.id.nav_send) {
                    Toast.makeText(Permissions_Display.this,"nav_send",Toast.LENGTH_LONG).show();
                }
            }
        });
Jayesh Babu
  • 1,389
  • 2
  • 20
  • 34
0

**

For Menu Items Clickable

** NavController offers an OnDestinationChangedListener interface that is called when the NavController's current destination or its arguments change. A new listener can be registered via the addOnDestinationChangedListener() method. Note that when calling addOnDestinationChangedListener(), if the current destination exists, it is immediately sent to your listener.

////////////////////////////////////////////////////////////////////////

navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
   @Override
   public void onDestinationChanged(@NonNull NavController controller,
           @NonNull NavDestination destination, @Nullable Bundle arguments) {
       if(destination.getId() == R.id.gallery) {
           //statements
       } else {
       //statements
}
   }
});
0
navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
    @Override
    public void onDestinationChanged(@NonNull NavController controller,
                                     @NonNull NavDestination destination, @Nullable Bundle arguments) {
        if(destination.getId() == R.id.nav_cart) {
            Toast.makeText(HomeActivity.this,"nav_cart",Toast.LENGTH_LONG).show();
        } if(destination.getId() == R.id.nav_orders) {
            Intent in =new Intent(HomeActivity.this, OrdersActivity.class);
            startActivity(in);
            Toast.makeText(HomeActivity.this,"nav_gallery",Toast.LENGTH_LONG).show();
        }
        if(destination.getId() == R.id.nav_categories) {
            Toast.makeText(HomeActivity.this,"nav_categories",Toast.LENGTH_LONG).show();
        }
        if(destination.getId() == R.id.nav_settings) {
            Intent in =new Intent(HomeActivity.this, SettingsActivity.class);
            startActivity(in);
            Toast.makeText(HomeActivity.this,"nav_settings",Toast.LENGTH_LONG).show();
        } if(destination.getId() == R.id.nav_logout) {
            Toast.makeText(HomeActivity.this,"nav_logout",Toast.LENGTH_LONG).show();
        }
    }
});
David Buck
  • 3,752
  • 35
  • 31
  • 35