How to replace the hamburger icon used for ActionBarToggle on Android Toolbar with a custom drawable?
Asked Answered
T

10

39

I have implemented a basic ActionBarDrawerToggle using the new Toolbar in Android 5.0.

However, I am unable to figure out how to change the default hamburger icon that is supplied. From the android documentation it says that "the given Activity will be linked to the specified DrawerLayout and the Toolbar's navigation icon will be set to a custom drawable... This drawable shows a Hamburger icon when drawer is closed and an arrow when drawer is open. It animates between these two states as the drawer opens."

I currently have this all working correctly with the following code, however I want to replace the default supplied hamburger with my own drawable.

Here is my current code:

MainActivity.java

@InjectView(R.id.main_activity_toolbar)
Toolbar mToolbar;

@InjectView(R.id.main_activity_drawer_layout)
DrawerLayout mDrawerLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.main_activity);
    super.onCreate(savedInstanceState);

    setSupportActionBar(mToolbar);
    mToolbar.setNavigationIcon(R.drawable.navigation);

    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.drawer_open, R.string.drawer_close) {
        public void onDrawerClosed(View view) {
            super.onDrawerClosed(view);
            invalidateOptionsMenu();
        }

        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            invalidateOptionsMenu();
        }
    };

    mDrawerLayout.setDrawerListener(mDrawerToggle);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setHomeButtonEnabled(true);
}

This line:

mToolbar.setNavigationIcon(R.drawable.navigation);

doesn't seem to work.

Is this possible to do? Thanks!

ActionBarToggle Documentation - https://developer.android.com/reference/android/support/v7/app/ActionBarDrawerToggle.html

Thoroughfare answered 19/11, 2014 at 22:52 Comment(1)
I've created a simplified version of ActionBarDrawerToggle that uses a drawable from resources: StaticActionBarDrawerToggle classTapir
L
29

You can use the toolbar as Stand Alone mode, that means you should not use your toolbar as part of your ActionBarDrawerToggle constructor, you can achieve that using the below code:

mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, null,
                       R.drawable.appbar, R.drawable.appbar)

(Note how the toolbar instance is not being sent to the ActionBarDrawerToggle constructor)

Also, you should inflate your menu manually

mToolbar = (Toolbar) findViewById(R.id.nav_toolbar);
mToolbar.inflateMenu(R.menu.base);

And remove the setSupportActionBar(mToolbar); line of code.

Of course, you will have to handle the navigation click by yourself:

mToolbar.setOnMenuItemClickListener(new OnMenuItemClickListener() ...

Then, you can open your drawer like this:

drawerButton = (BadgeDrawerButton) findViewById(R.id.badge_drawer_button);
drawerButton.setOnClickListener(
                       new View.OnClickListener() {

                              @Override
                              public void onClick(View v) {
                                     mDrawerLayout.openDrawer(Gravity.LEFT);
                              }
                       });

Hope this may help.

Lippert answered 24/11, 2014 at 23:27 Comment(5)
Thanks for the advice! This does work, but how do you get the icon to go to the left side of the menu bar? Also, have to keep track of whether the drawer is open to know if you should call openDrawer or closeDrawer, correct?Thoroughfare
If you use the mToolbar.setNavigationIcon(resId); it will place it for you. Yes, you need to keep track of the drawer status (open, close) but I omitted those line for brevity sake. Please mark the answer if this helped you.Lippert
if(mDrawerLayout.isDrawerOpen()) { mDrawerLayout.closeDrawer(mDrawer); } else { mDrawerLayout.openDrawer(mDrawer); }Colp
It is not clear what need to be done. Do I need to add a drawer icon to the menu? I tried it and now I have 2 custom icons on the toolbar but of none of them handles click events. I guess this is because I did not implement the onClick of the drawerButton but I do not know how to handle it (could not find a reference to BadgeDrawerButton) and where is the button defined.Undercoat
I believe this answer is for the v4 support library and will not work with the v7 library.Sandarac
P
29

These two lines of code work for me:

mDrawerToggle.setDrawerIndicatorEnabled(false); //disable "hamburger to arrow" drawable
mDrawerToggle.setHomeAsUpIndicator(R.drawable.ic_drawer); //set your own

And then call this:

mDrawerToggle.syncState();
Padishah answered 21/8, 2015 at 11:39 Comment(3)
Has its own problems. The moment you popBackStack on the fragmentManager, the stock hamburger icon comes back.Globetrotter
your code changing icon, but the click of icon has gone.Quicksilver
We can follow these steps to resolve this issue mobikul.com/change-hamburger-icon-androidLianneliao
P
9

The default menu drawable for the ActionBarDrawerToggle is DrawerArrowDrawable.

You can subclass this to add custom functionality, like badges, like so:

public class BadgedDrawerArrowDrawable extends DrawerArrowDrawable {

    /**
     * @param context used to get the configuration for the drawable from
     */
    public BadgedDrawerArrowDrawable(Context context) {
        super(context);

        setColor(context.getResources().getColor(R.color.colorAccent));
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.RED);
        paint.setTextSize(60);
        canvas.drawText("!", canvas.getWidth() - 60, 25, paint);
    }
}

Usage:

actionBarDrawerToggle.setDrawerArrowDrawable(new BadgedDrawerArrowDrawable(activity));
Pernod answered 23/11, 2016 at 21:51 Comment(1)
Brilliant. Perfect solution for badging the hamburger. The only thing I point out is not allocate Paint in the draw() call.Loss
C
7

My solution is by subclassing ActionBarDrawerToggle.

public class MyActionBarDrawerToggle extends android.support.v7.app.ActionBarDrawerToggle {

    public MyActionBarDrawerToggle(Activity activity, final DrawerLayout drawerLayout, Toolbar toolbar, int openDrawerContentDescRes, int closeDrawerContentDescRes) {
        super(activity, drawerLayout, toolbar, openDrawerContentDescRes, closeDrawerContentDescRes);

        setHomeAsUpIndicator(R.drawable.drawer_toggle);
        setDrawerIndicatorEnabled(false);

        setToolbarNavigationClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                drawerLayout.openDrawer(Gravity.LEFT);
            }
        });
     }
}
Cerebrovascular answered 4/7, 2015 at 4:19 Comment(0)
V
6

the thing that worked for me is that i just needed to call toolbar.setNavigationIcon(R.drawable.ic_camera_alt_24dp); at the end of onCreate, or at least after mDrawerToggle = new ActionBarDrawerToggle...

Vesicate answered 19/2, 2016 at 9:33 Comment(1)
Not working. Same problem as the answer above - once you press the Up arrow to close the drawer the stock hamburger icon shows up, temporarily, and then it is replaced with the custom icon. I am looking for a solution that eliminates it completely.Undercoat
N
5
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
final ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this,drawer,toolbar,R.string.navigation_drawer_open,R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);

toggle.syncState();
toolbar.setNavigationIcon(R.drawable.ic_action_name);
Naphtha answered 20/9, 2017 at 11:33 Comment(0)
D
3

as of Jan 2018, this is a working solution (at least for me):

    //setSupportActionBar(toolbar)

    val toggle = ActionBarDrawerToggle(this, drawer_layout, null, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
    toolbar.inflateMenu(R.menu.menu_main)
    toolbar.setNavigationIcon(R.drawable.ic_menu)
    toolbar.setNavigationOnClickListener {
        drawer_layout.openDrawer(Gravity.START)
    }

    toolbar.setOnMenuItemClickListener {
        true
    }

    drawer_layout.addDrawerListener(toggle)
    toggle.syncState()

    nav_view.setNavigationItemSelectedListener(this)

things to care:

  • setSupportActionBar should be commented out
  • ActionBarDrawerToggle is not taking a reference to toolbar
  • We should inflate menu ourself, and handle onClicks. onCreateOptionsMenu and onOptionsItemSelected will not be functioning.
  • Don't forget to call toggle.syncState()
Doggery answered 3/1, 2018 at 14:36 Comment(0)
F
2

As for v7 support library - you can create your own representation of DrawerArrowDrawable.

mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {

            public void onDrawerClosed(View view) {
                supportInvalidateOptionsMenu();
            }

            public void onDrawerOpened(View drawerView) {
                supportInvalidateOptionsMenu();
            }
        };
        mDrawerToggle.setDrawerIndicatorEnabled(true);

        DrawerArrowDrawable drawerArrowDrawable = new DrawerArrowDrawable(this);
        drawerArrowDrawable.setAlpha(1);
        drawerArrowDrawable.setSpinEnabled(false);
        drawerArrowDrawable.setDirection(DrawerArrowDrawable.ARROW_DIRECTION_LEFT);
        drawerArrowDrawable.setColor(Color.BLACK);

        mDrawerToggle.setDrawerArrowDrawable(drawerArrowDrawable);
Flem answered 27/9, 2017 at 6:58 Comment(0)
D
1

Here's how I was able to finally get mine to work.

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

if (toolbar != null) {
    setSupportActionBar(toolbar);
    toolbar.setNavigationIcon(R.drawable.ic_drawer);

    mDrawerToggle = new ActionBarDrawerToggle(this,
                mDrawerLayout,
                toolbar,
                R.string.drawer_open,
                R.string.drawer_close) {

        /** Called when a drawer has settled in a completely closed state. */
        public void onDrawerClosed(View view) {
            super.onDrawerClosed(view);
        }

        /** Called when a drawer has settled in a completely open state. */
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
        }
    };

    // Set the drawer toggle as the DrawerListener
    mDrawerLayout.setDrawerListener(mDrawerToggle);
    mDrawerToggle.syncState();

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setHomeButtonEnabled(true);
}

It turned out to be the

mDrawerToggle.syncState();

That finally got everything to work.

Durrace answered 24/11, 2014 at 23:35 Comment(0)
I
0

I think it is recommended to put the call to syncState() in the onPostCreate(...) lifecycle method.

@Override
public void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    mDrawerToggle.syncState();
}
Irra answered 11/7, 2016 at 23:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.