I am trying to access navigation drawer so that when i click on the top left corner of app bar, I can access settings in a new activity

Viewed 605

I am trying to access navigation drawer so that when i click on the top left corner of app bar, I can access settings in a new activity. Right now what I get when I click on the upper left corner and then click settings is the menu retracts and nothing else happens. I have a bottom navigation bar also. Please help. Here's what I have so far:

NavigationActivity.java

package com.tt.lateoclock;

import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.widget.Toolbar;

import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationView;
import com.google.firebase.database.DatabaseReference;
import com.tt.lateoclock.Prevalent.Prevalent;
import com.tt.lateoclock.ui.findFood.FindFoodFragment;


import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;

import androidx.core.content.ContextCompat;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.recyclerview.widget.RecyclerView;
import de.hdodenhof.circleimageview.CircleImageView;

public class NavigationActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, BottomNavigationView.OnNavigationItemSelectedListener {

    DrawerLayout drawer;
    NavigationView navigationView;
    Menu menu;

    private DatabaseReference merchantRef;
    RecyclerView recyclerView;
    RecyclerView.LayoutManager layoutManager;
    ActionBarDrawerToggle toggle;
    Intent settingsIntent;
    NavController navController;
    AppBarConfiguration appBarConfiguration;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_navigation);


        //merchantRef = FirebaseDatabase.getInstance().getReference().child("Merchants");


        Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        toolbar.setTitle("Home");


        drawer = findViewById(R.id.container);
        toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);

        drawer.addDrawerListener(toggle);
        toggle.syncState();

        navigationView = findViewById(R.id.nav_view);

        BottomNavigationView navView = findViewById(R.id.bot_nav_view);

        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_find_food, R.id.navigation_favorites, R.id.navigation_map, R.id.navigation_receipts, R.id.navigation_settings)
                .build();
        navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        NavigationUI.setupWithNavController(navView, navController);

        View headerView = navigationView.getHeaderView(0);
        TextView name = (TextView)headerView.findViewById(R.id.username);
        CircleImageView user_image = (CircleImageView)headerView.findViewById(R.id.user_image);

        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                int id=menuItem.getItemId();
                Toast.makeText(getApplicationContext(), id, Toast.LENGTH_SHORT).show();
                //it's possible to do more actions on several items, if there is a large amount of items I prefer switch(){case} instead of if()
                if (id==R.id.navigation_settings){
                    Toast.makeText(getApplicationContext(), "Settings", Toast.LENGTH_SHORT).show();
                }
                //This is for maintaining the behavior of the Navigation view
                NavigationUI.onNavDestinationSelected(menuItem, navController);
                //This is for closing the drawer after acting on it
                drawer.closeDrawer(GravityCompat.START);
                return true;
            }
        });


        name.setText(Prevalent.currentUser.getName());
        
        navigationView.setNavigationItemSelectedListener(this);


    }

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController=Navigation.findNavController(this, R.id.nav_host_fragment);
        return NavigationUI.navigateUp(navController, appBarConfiguration)
                || super.onSupportNavigateUp();
    }

    @Override
    public void onBackPressed()
    {
        if(drawer.isDrawerOpen(GravityCompat.START))
        {
            drawer.closeDrawer(GravityCompat.START);
        }
        else{
            super.onBackPressed();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
            case R.id.navigation_settings:
                settingsIntent = new Intent(this, SettingsActivity.class);
                startActivity(settingsIntent);


            default:
                return super.onOptionsItemSelected(item);
        }
    }


    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.navigation_find_food:
                getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new FindFoodFragment()).commit();
                break;
            case R.id.navigation_favorites:
                getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new com.tt.lateoclock.ui.favorites.FavoritesFragment()).commit();
                break;
            case R.id.navigation_receipts:
                getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new com.tt.lateoclock.ui.receipts.ReceiptsFragment()).commit();
                break;

            case R.id.navigation_settings:
                Toast.makeText(this, "Settings selected", Toast.LENGTH_SHORT).show();
                Intent settingsIntent = new Intent(this, SettingsActivity.class);
                startActivity(settingsIntent);
                Toast.makeText(this, "Settings selected", Toast.LENGTH_SHORT).show();
                return true;
        }
        return true;
    }
}

activity_navigation.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/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".NavigationActivity">

    <com.google.android.material.navigation.NavigationView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:id="@+id/nav_view"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/drawer_menu"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <fragment
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_marginTop="?android:attr/actionBarSize"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/mobile_navigation" />

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimaryDark"
            android:elevation="4dp"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            />
        
<com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bot_nav_view"
            android:layout_width="match_parent"
            android:layout_height="196dp"
            android:layout_below="@id/nav_host_fragment"
            android:layout_marginTop="-100dp"
            android:layout_gravity="bottom"
            android:background="?android:attr/windowBackground"
            app:menu="@menu/bottom_nav_menu" >
        </com.google.android.material.bottomnavigation.BottomNavigationView>
    </RelativeLayout>

</androidx.drawerlayout.widget.DrawerLayout>

bottom_nav_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/navigation_find_food"
        android:icon="@drawable/ic_local_dining_black_24dp"
        android:title="@string/title_find_food" />

    <item
        android:id="@+id/navigation_favorites"
        android:icon="@drawable/ic_favorite_black_24dp"
        android:title="@string/title_favorites" />

    <item
        android:id="@+id/navigation_map"
        android:icon="@drawable/ic_map_black_24dp"
        android:title="@string/title_map" />

    <item
        android:id="@+id/navigation_receipts"
        android:icon="@drawable/ic_receipt_black_24dp"
        android:title="@string/title_receipts" />

</menu>

drawer_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

        <item android:id="@+id/nav_message"
            android:title="Message"
            android:icon="@drawable/ic_message"/>

        <item android:id="@+id/nav_profile"
            android:title="Profile"
            android:icon="@drawable/ic_profile"/>

        <item android:id="@+id/navigation_settings"
            android:title="Settings"
            android:icon="@drawable/ic_settings_black_24dp"
            android:enabled="true"/>
</menu>

mobile_navigation.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/mobile_navigation"
    app:startDestination="@+id/navigation_find_food">

    <fragment
        android:id="@+id/navigation_find_food"
        android:name="com.tt.lateoclock.ui.findFood.FindFoodFragment"
        android:label="@string/title_find_food"
        tools:layout="@layout/fragment_find_food" />

    <fragment
        android:id="@+id/navigation_favorites"
        android:name="com.tt.lateoclock.ui.favorites.FavoritesFragment"
        android:label="@string/title_favorites"
        tools:layout="@layout/fragment_favorites" />

    <fragment
        android:id="@+id/navigation_map"
        android:name="com.tt.lateoclock.ui.map.MapFragment"
        android:label="@string/title_map"
        tools:layout="@layout/fragment_map" />

    <fragment
        android:id="@+id/navigation_receipts"
        android:name="com.tt.lateoclock.ui.receipts.ReceiptsFragment"
        android:label="@string/title_receipts"
        tools:layout="@layout/fragment_receipts" />

</navigation>
4 Answers

Just change the activity_navigation.xml to

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
    ...>

    <RelativeLayout...>

    <com.google.android.material.navigation.NavigationView
        android:layout_gravity="start"
         .../>

</androidx.drawerlayout.widget.DrawerLayout>

Also you have to handle the click on the settings item with navigationView.setNavigationItemSelectedListener.

About the DrawerLayout check the doc:

Note: When using NavigationUI, the top app bar helpers automatically transition between the drawer icon and the Up icon as the current destination changes. You don't need to use ActionBarDrawerToggle.

In your code remove the code about the ActionBarDrawerToggle and use:

AppBarConfiguration appBarConfiguration =
        new AppBarConfiguration.Builder(...........)
            .setDrawerLayout(drawerLayout)
            .build();

Here your Setting activity is not a part of the NavigationGraph (i.e. not a fragment it's a separate activity).

And when you hit the drawer burger and choose the Setting, it won't go to the Setting as you didn't launch the intent on the OnNavigationItemSelectedListener of the NavigationView

To fix that:

navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        int id=menuItem.getItemId();
        Toast.makeText(getApplicationContext(), id, Toast.LENGTH_SHORT).show();
        //it's possible to do more actions on several items, if there is a large amount of items I prefer switch(){case} instead of if()
        if (id==R.id.navigation_settings){
            Toast.makeText(getApplicationContext(), "Settings", Toast.LENGTH_SHORT).show();
            Intent settingsIntent = new Intent(NavigationActivity.this, SettingsActivity.class); // <<< Here is the change
            startActivity(settingsIntent); // <<< Here is the change
        }
        //This is for maintaining the behavior of the Navigation view
        NavigationUI.onNavDestinationSelected(menuItem, navController);
        //This is for closing the drawer after acting on it
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
});

Update

Replace

navigationView.setNavigationItemSelectedListener(this);

With

navView.setNavigationItemSelectedListener(this);

You can add an <activity> destination to your navigation graph for starting another activity:

<activity
    android:id="@+id/navigation_settings"
    android:name="com.your.package.SettingsActivity" />

Then, the default behavior of setupWithNavController() / onNavDestinationSelected() will start your activity for you. You wouldn't need to write any custom code or manual calls to setNavigationItemSelectedListener to get this behavior.

You should also strongly consider adding menuCategory="secondary" to your navigation_settings menu item as per the onNavDestinationSelected() documentation to avoid your current destination from being popped off the back stack.

Add the OnClick method in the menu item

<item
     android:id="@+id/nav_whats_app"
     android:icon="@drawable/ic_menu_settings"
     android:title="@string/menu_settings"
     android:onClick="onOpenSettings" />

Then add the method in the activity like this

//Kotlin Android
fun onOpenSettings(item: MenuItem) {
//... open settings here
}

Java Code

//Java Android
void onOpenSettings(MenuItem item) {
//... open settings here
}

To close any Navigation drawer, just call

val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
    if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
        drawerLayout.closeDrawer(GravityCompat.START)
    }
Related