Clicking hamburger icon on Toolbar does not open Navigation Drawer

69.2k Views Asked by At

I have a simple android.support.v7.widget.Toolbar and all I am trying to do is to open a NavigationDrawer by pressing the "hamburger" icon in the top left corner. The "hamburger" button is visible, and when I start to pull from the left I see the animation on the button but pressing the button does not open/close the NavigationDrawer as I expect. I have followed the [Google Documentation][1] and still am not able to figure this out. Sorry for any confusion, below is the simplified code I am currently attempting to use:

public class MainActivity extends AppCompatActivity implements
    View.OnClickListener,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener {



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


    setContentView(R.layout.activity_main);


    Toolbar toolbar = (Toolbar) findViewById(R.id.my_toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);



    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d("NICK", "button button button..................");
        }
    });

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer);
        NavigationView n = (NavigationView) findViewById(R.id.nav);
        mDrawerLayout.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Log.d("NICK", "button button button..................");
            }
        });

        //mDrawerLayout.setDrawerListener(mDrawerToggle);
        n.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {
                switch (menuItem.getItemId()) {
                    ////.......

                }
                mDrawerLayout.closeDrawers();  // CLOSE DRAWER
                return true;
            }
        });

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    Log.d("NICK","CWECNEWKVNERIPNVIEWNFVIPEWNVIPEWNVPIEWNVPIEWNVPIEWNVPIRWNVPRWVPO");
    switch (item.getItemId()) {
        case android.R.id.home:
            mDrawerLayout.openDrawer(GravityCompat.START);  // OPEN DRAWER
            Log.d("NICK","CWECNEWKVNERIPNVIEWNFVIPEWNVIPEWNVPIEWNVPIEWNVPIEWNVPIRWNVPRWVPO");
            return true;

    }
           return super.onOptionsItemSelected(item);


}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mDrawerToggle.onConfigurationChanged(newConfig);
}



@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.drawer, menu);
    return true;
}


}

}

And as it is I do not get any of the log debug statements when running.

This is essentially the issue I have: https://stackoverflow.com/a/26636045/1489990. I've followed this and it just doesn't work.

It is my understanding that setNavigationOnClickListener is called when the hamburger icon is pressed, and this is where I am focusing my efforts is to get the event handled properly because when I press the button I do not get my log statement. Let me know if this idea is incorrect. https://developer.android.com/reference/android/widget/Toolbar.html#setNavigationOnClickListener(android.view.View.OnClickListener)

My Layouts:

ActivityMain.xml

<RelativeLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/d"
android:background="@drawable/home_wall">




<android.support.v7.widget.Toolbar
    android:id="@+id/my_toolbar"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:layout_marginBottom="10dp"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:layout_marginTop="25dp"

    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" />



<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:id="@+id/drawer"

    android:layout_height="match_parent"
    android:fitsSystemWindows="true">



    <ImageView
        android:layout_width="fill_parent"
        android:layout_height="200dp"
        android:id="@+id/imageView"
        android:src="@drawable/trans2"
        android:layout_alignParentTop="true"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:paddingBottom="300dp" />

    <RelativeLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/d8"
        android:layout_alignParentTop="true"
        android:layout_alignLeft="@+id/imageView"
        android:layout_alignStart="@+id/imageView"
        android:paddingTop="0dp">

        <Button
            android:layout_width="75dp"
            android:layout_height="50dp"
            android:text="Gallery"
            android:id="@+id/save_button"
            android:background="#dd2c00" android:textColor="#fff"
            android:layout_below="@+id/Purchases"
            android:layout_toRightOf="@+id/start_button"
            android:layout_toEndOf="@+id/start_button" />
        <Button
            android:layout_width="125dp"
            android:layout_height="50dp"
            android:text="Store"
            android:id="@+id/Purchases"
            android:background="#ff6e40" android:textColor="#fff"
            android:layout_above="@+id/instructions_button6"
            android:layout_toLeftOf="@+id/start_button"
            android:layout_toStartOf="@+id/start_button"
            android:layout_marginBottom="98dp" />
        <Button
            android:layout_width="75dp"
            android:layout_height="50dp"
            android:text="Help"
            android:id="@+id/instructions_button6"
            android:background="#dd2c00" android:textColor="#fff"
            android:layout_alignParentBottom="true"
            android:layout_toLeftOf="@+id/start_button"
            android:layout_toStartOf="@+id/start_button"
            android:layout_marginLeft="5dp"
            android:layout_marginBottom="10dp" />
        <Button
            android:layout_width="75dp"
            android:layout_height="300dp"
            android:text="Start"
            android:id="@+id/start_button"
            android:background="#ff3d00"
            android:textColor="#fff"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="10dp" />
        <Button
            android:layout_width="125dp"
            android:layout_height="50dp"
            android:text="Achievements"
            android:id="@+id/Scores"
            android:background="#ff6e40" android:textColor="#fff"
            android:layout_alignTop="@+id/Purchases"
            android:layout_toRightOf="@+id/start_button"
            android:layout_toEndOf="@+id/start_button" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Welcome to the quiz!"
            android:id="@+id/textView"
            android:textColor="#fff"
            android:textSize="20dp"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="70dp" />


        <!-- sign-in button -->
        <com.google.android.gms.common.SignInButton
            android:id="@+id/sign_in_button"
            android:layout_width="110dp"
            android:layout_height="50dp"
            android:layout_above="@+id/start_button"
            android:layout_centerHorizontal="true"
            android:visibility="visible" />

        <!-- sign-out button -->
        <Button
            android:id="@+id/sign_out_button"
            android:layout_width="125dp"
            android:layout_height="wrap_content"
            android:text="Sign Out"
            android:visibility="invisible"
            android:background="#dd4b39"
            android:textColor="#fff"
            android:layout_alignTop="@+id/sign_in_button"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="160dp" />

    </RelativeLayout>

    <android.support.design.widget.NavigationView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#fff"
        android:id="@+id/nav"

        app:headerLayout="@layout/drawer_header"
        app:menu="@menu/drawer"/>
</android.support.v4.widget.DrawerLayout>

Drawer.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_menu"
xmlns:app="http://schemas.android.com/apk/res-auto">

<item android:title="Google Play Games"

    android:icon="@drawable/ic_local_airport_white_48dp">
    <menu>
        <item
            android:id="@+id/Sign_in_drawer"

            android:icon="@drawable/games_controller_grey"
            android:title="Sign in" />
        <item
            android:id="@+id/ach"
            android:icon="@drawable/games_achievements"
            android:title="Achievements" />
    </menu>
</item>

<item android:title="Start a Quiz"

   android:icon="@drawable/ic_local_airport_white_48dp">
    <menu>
        <item
            android:id="@+id/quizStart25"

            android:icon="@drawable/ic_local_airport_white_48dp"
            android:title="25 Questions" />
        <item
            android:id="@+id/quizStart10"
            android:icon="@drawable/ic_local_airport_white_48dp"
            android:title="10 Questions" />
    </menu>
</item>

<group
    android:checkableBehavior="single">
    <item
        android:id="@+id/gallery"

        android:icon="@drawable/ic_photo_library_white_48dp"
        android:title="Gallery" />
    <item
        android:id="@+id/stats"
        android:icon="@drawable/ic_toc_white_48dp"
        android:title="Statistics" />
    <item
        android:id="@+id/store"
        android:icon="@drawable/ic_shop_white_48dp"
        android:title="Store" />
    <item
        android:id="@+id/settings"
        android:icon="@drawable/ic_settings_white_48dp"
        android:title="Settings" />
    <item
        android:id="@+id/about"
        android:icon="@drawable/ic_info_white_48dp"
        android:title="About" />

</group>

<item android:title="Support">
    <menu>
        <item
            android:id="@+id/help_drawer"
            android:icon="@drawable/ic_help_white_48dp"
            android:title="Help" />
        <item
            android:id="@+id/report"
            android:icon="@drawable/ic_report_problem_white_48dp"
            android:title="Contact Developer" />
        <item
            android:id="@+id/GPlusCommunity"
            android:icon="@drawable/btn_g_white_normal"
            android:title="Google+ Community" />

    </menu>
</item>

17

There are 17 best solutions below

10
On BEST ANSWER

In your ActivityMain.xml, the toolbar is outside of the DrawerLayout. That's the problem. If you want Toolbar to interact with DrawLayout, Toolbar needs to be a child of DrawerLayout.

To fix the problem, make DrawerLayout the root of your activity. Here's the documentation. The relevant quote is:

To add a navigation drawer, declare your user interface with a DrawerLayout object as the root view of your layout. Inside the DrawerLayout, add one view that contains the main content for the screen (your primary layout when the drawer is hidden) and another view that contains the contents of the navigation drawer.

So basically, structure your ActivityMain.xml to be something like this:

<android.support.v4.widget.DrawerLayout ...>

    <RelativeLayout ...>

        <android.support.v7.widget.Toolbar .../>

        <!-- Your other content goes here -->

    </RelativeLayout>

    <android.support.design.widget.NavigationView .../>

</android.support.v4.widget.DrawerLayout>

That should take care of the problem.

2
On

You need to sync the drawer toggle:

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    // Sync the toggle state after onRestoreInstanceState has occurred.
    mDrawerToggle.syncState();
}

EDIT: That code is working for me (copied from your post)

public class TempActivity extends AppCompatActivity {
    private ActionBarDrawerToggle mDrawerToggle;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.temp);
        setupDrawer();
    }
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mDrawerToggle.onConfigurationChanged(newConfig);
    }
    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        mDrawerToggle.syncState();
    }
    private void setupDrawer() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.my_toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
        DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.my_drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,toolbar,R.string.drawer_open, R.string.drawer_close) {
            public void onDrawerClosed(View view) {
                super.onDrawerClosed(view);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            }
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);
    }
}

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/my_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <android.support.v7.widget.Toolbar
            android:id="@+id/my_toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
        <FrameLayout
            android:id="@+id/content_frame"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>
    <RelativeLayout
        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">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#FFF"
            android:text="DRAMER MENU" />
    </RelativeLayout>
</android.support.v4.widget.DrawerLayout>

But if you are using the new NavigationView, then you don't need the toggle etc. Here is a good example how to use it.

1
On

For the drawer toggle you need to set "display home as up" to false: getSupportActionBar().setDisplayHomeAsUpEnabled(false);

0
On

As i have no specific answer to your problem, i want to suggest a completely different approach:

In my projects im using the Material Drawer developed by Mike Penz. Its looks really nice, is easy to implement, and there is not much you have to worry about.

So if you cant find a solution for your problem, you could give it a try.

0
On

Firstly, follow instruction provided by accepted answer.

Then Make sure you assign right constructor for toggle - i.e,

val toggle = ActionBarDrawerToggle(this, binding.root, toolbar, R.string.OpenDrawer, R.string.CloseDrawer)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()

wher drawerLayout is val drawerLayout = findViewById(R.id.drawer)

As there are two type of constructor for ActionBarDrawerToggle()

1 - ActionBarDrawerToggle(
    Activity activity,
    DrawerLayout drawerLayout,
    @StringRes int openDrawerContentDescRes,
    @StringRes int closeDrawerContentDescRes
)

2- ActionBarDrawerToggle(
    Activity activity,
    DrawerLayout drawerLayout,
    Toolbar toolbar,
    @StringRes int openDrawerContentDescRes,
    @StringRes int closeDrawerContentDescRes
)

Use second option to assign toggle to your toolbar.

You can read official documentation here

2
On

I fixed it by giving openable which is drawerLayout to navigateUp function.

More info navigateUp Doc

 override fun onSupportNavigateUp(): Boolean {
    val navController = this.findNavController(R.id.host_fragment)
    return NavigationUI.navigateUp(navController,drawer_layout)
}
0
On

Simply call function onOptionsItemSelected(MenuItem menuItem) of ActionBarDrawerToggle class on activity options menu managing function like below.

mDrawerToggle= new ActionBarDrawerToggle(activity, drawerLayout, R.string.nav_drawer_accessbility_drawer_open,
            R.string.nav_drawer_accessbility_drawer_close);


 @Override
public boolean onOptionsItemSelected(final android.view.MenuItem item) {
    navigation().getOptionsMenuInflater(this).closeSearchView();
    // The action bar home/up action should open or close the drawer.
    // ActionBarDrawerToggle will take care of this behavior.
    mDrawerToggle.onOptionsItemSelected(item);

    return super.onOptionsItemSelected(item);
}

OR

override onOptionsItemSelected of activity like below

public boolean onOptionsItemSelected(MenuItem item) {
    if (item != null && item.getItemId() == android.R.id.home) {
        toggle();

    }
    return super.onOptionsItemSelected(item);
}

 private void toggle() {
    if (mDrawerLayout.isDrawerVisible(GravityCompat.START)) {
        mDrawerLayout.closeDrawer(GravityCompat.START);
    } else {
        mDrawerLayout.openDrawer(GravityCompat.START);
    }
}
0
On

I had the same problem. However, it did not occur on all fragments. It occurred on one particular fragment.

Firstly, please follow @hungryghost 's answer mentioned above. Then do the following. Adding the following piece of code helped the drawer open on click of the hamburger icon. It worked flawlessly for me. Thank you very much. :) My sincere apologies if this isn't the right way.

@Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        int itemId = item.getItemId();        
        if(itemId == android.R.id.home){
            NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
            return NavigationUI.navigateUp(navController, mAppBarConfiguration)
                    || super.onSupportNavigateUp();
        }
        return super.onOptionsItemSelected(item);
    }

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

I'm missing this one outside of the onCreate method.

override fun onSupportNavigateUp(): Boolean {
    val navController = findNavController(R.id.nav_host_fragment)
    return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
0
On

While accepted answer here works alright however, as they say "Prevention is better than cure".. Adding mDrawerToggle.syncState(); in onPostCreate and onConfigurationChanged() wroks much better as answerd by @mbmc above:

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    // Sync the toggle state after onRestoreInstanceState has occurred.
    mDrawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mDrawerToggle.onConfigurationChanged(newConfig);
}
0
On

Override onOptionsItemSelected method and use below

if(item.getItemId() == android.R.id.home){ // use android.R.id
    mDrawerLayout.openDrawer(Gravity.LEFT);
}
0
On

Use ActionBarDrawerToggle and implement public boolean onOptionsItemSelected(MenuItem item)

Toolbar DOES NOT have to be within a DrawerLayout, it's not likely to be the cause of this issue. toggle.onOptionsItemSelected(item) looks for the ID of the item selected and if it is android.R.id.home then the drawer's visibility is toggled. Thus Toolbar, or any View that creates a Home MenuItem, can be placed anywhere in your layout.

Within your activity:

ActionBarDrawerToggle toggle;

private void setupDrawerToggleInActionBar() {
    // assuming a Toolbar has been initialized in your onCreate
    this.setSupportActionBar(toolbar);

    // setup the action bar properties that give us a hamburger menu
    ActionBar actionBar = this.getSupportActionBar();
    if(actionBar != null) {
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);
    }

    // the toggle allows for the simplest of open/close handling
    toggle = new ActionBarDrawerToggle(this,
                                       drawerLayout,
                                       R.string.navigation_drawer_open,
                                       R.string.navigation_drawer_close);
    // drawerListener must be set before syncState is called
    drawerLayout.setDrawerListener(toggle);

    toggle.setDrawerIndicatorEnabled(true);
    toggle.syncState();
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    // This is required to make the drawer toggle work
    if(toggle.onOptionsItemSelected(item)) {
        return true;
    }

    /*
     * if you have other menu items in your activity/toolbar 
     * handle them here and return true
     */

    return super.onOptionsItemSelected(item);
}
0
On

After a lot of different problems I found a way to make it work putting Toolbar Widget inside AppBarLayout.

Be sure that there is no other layout on top of widget toolbar!

<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/drawable_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

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

        <com.google.android.material.appbar.AppBarLayout 
         android:layout_width="match_parent"
          android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        xmlns:android="http://schemas.android.com/apk/res/android">**

          <androidx.appcompat.widget.Toolbar 
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/main_page_toolbar"
          android:layout_width="match_parent" android:layout_height="wrap_content"
          android:background="@color/colorPrimaryDark"
          android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

          </androidx.appcompat.widget.Toolbar>
         </com.google.android.material.appbar.AppBarLayout>**

        .... YOUR LAYOUT ...

    </RelativeLayout>

    <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:layout_marginBottom="3dp"
        app:menu="@menu/navigation_menu">

    </com.google.android.material.navigation.NavigationView>

</androidx.drawerlayout.widget.DrawerLayout>
0
On

Idk why...but changing return value to false rather than true fixed the ham Icon for me. on onOptionItemSelected override method

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    super.onOptionsItemSelected(item);
    if(item.getItemId() == R.id.logout){
        ParseUser.logOut();
        Intent intent = new Intent(getApplicationContext(), MainActivity.class);
        startActivity(intent);
        Toast.makeText(this, "Logout Successful!", Toast.LENGTH_SHORT).show();
    } else if(item.getItemId() == R.id.action_settings){
        Toast.makeText(this, "No setting to update! Will be available later...", Toast.LENGTH_SHORT).show();
    }
    return true; // here change this to false
}
1
On

I have found a simple solution to this problem is to call the setSupportActionBar(toolbar) method before the navigation drawer functions.

0
On

If it helps somebody, to me it happened the same because of the stupid error of calling setSupportActionBar(toolbar) two times. Just call it once in onCreate method and never again. My mistake was I called it later in another method.

0
On

If none of the above answer works, please cross check again,

First you need to call setSupportActionBar(toolbar); and then do the necessary work for nav drawer. I wasted my 2 hours because of this silly mistake.