How to add "menu" indicator next to Action Bar's app icon?

39,074

Solution 1

To create similar implementation / look in your application you should use ActionBarDrawerToggle and set your custom icon as indicator next to ActionBar home button. For example :

import android.app.ActionBar;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;

private void setUpDrawerToggle(){
    ActionBar actionBar = getActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setHomeButtonEnabled(true);

    // ActionBarDrawerToggle ties together the the proper interactions
    // between the navigation drawer and the action bar app icon.
    mDrawerToggle = new ActionBarDrawerToggle(
            this,                             /* host Activity */
            mDrawerLayout,                    /* DrawerLayout object */
            R.drawable.ic_drawer,             /* nav drawer image to replace 'Up' caret */
            R.string.navigation_drawer_open,  /* "open drawer" description for accessibility */
            R.string.navigation_drawer_close  /* "close drawer" description for accessibility */
    ) {
        @Override
        public void onDrawerClosed(View drawerView) {
            invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }

        @Override
        public void onDrawerOpened(View drawerView) {
            invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }
    };

    // Defer code dependent on restoration of previous instance state.
    // NB: required for the drawer indicator to show up!
    mDrawerLayout.post(new Runnable() {
        @Override
        public void run() {
            mDrawerToggle.syncState();
        }
    });

    mDrawerLayout.setDrawerListener(mDrawerToggle);
}

Where R.drawable.ic_drawer is actually the icon to use as indicator. You can find it in Android Asset Studio; see Navigation Drawer Indicator.

References

  1. ActionBarDrawerToggle
  2. Creating a Navigation Drawer

Solution 2

Android-Developer and HpTerm helped me in the right rirection, by

  1. Pointing out this is indeed NavigationDrawer specific (which I was already using as in Google's example)
  2. Telling where to find the ic_drawer.png icon (→ Android Asset Studio)

Now, unfortunately, creating ActionBarDrawerToggle like below seems not to be enough. At least on my Nexus 7 (API 18) test device.

drawerToggle = new ActionBarDrawerToggle(this, 
                       drawerLayout, 
                       R.drawable.ic_navigation_drawer, 
                       R.string.side_menu_open, 
                       R.string.side_menu_closed) {
    // ...
};

Partial solution (API level 18+)

I found one way to make the indicator show up though: setHomeAsUpIndicator(). The downside: that method was added in API level 18.

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...
    getActionBar().setDisplayHomeAsUpEnabled(true); // also required
    if (Build.VERSION.SDK_INT >= 18) {
        getActionBar().setHomeAsUpIndicator(
            getResources().getDrawable(R.drawable.ic_navigation_drawer));
    }
}

So now the question remains: how to make this work (in my case) for API levels 14 through 17?

I verified on a 4.1.2 (API 16) device that the ic_drawer icon does not show up. With setDisplayHomeAsUpEnabled(true) I get the normal "home" icon (small arrow pointing left) and without it, the space left to my app icon remains blank.

Final solution

Got it working using the edited version of Android-Developer's answer.

Quite curiously, what was missing from my ActionBarDrawerToggle initialisation code was this:

   // Defer code dependent on restoration of previous instance state.
   drawerLayout.post(new Runnable() {
        @Override
        public void run() {
            mDrawerToggle.syncState();
        }
    });

With that included, calling setHomeAsUpIndicator() is not needed.

Solution 3

The keyword here is NavigationDrawer; there's a full working code example on the Android developer site.

READ THE END OF THE LINK GIVEN : Open and Close with the App Icon

The following code is copied from there

public class MainActivity extends Activity {
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    ...

    public void onCreate(Bundle savedInstanceState) {
        ...

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(
                this,                  /* host Activity */
                mDrawerLayout,         /* DrawerLayout object */
                R.drawable.ic_drawer,  /* nav drawer icon to replace 'Up' caret */
                R.string.drawer_open,  /* "open drawer" description */
                R.string.drawer_close  /* "close drawer" description */
                ) {

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

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

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

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

    @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);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Pass the event to ActionBarDrawerToggle, if it returns
        // true, then it has handled the app icon touch event
        if (mDrawerToggle.onOptionsItemSelected(item)) {
          return true;
        }
        // Handle your other action bar items...

        return super.onOptionsItemSelected(item);
    }

    ...
}

Some files are available as download and the small 3 lines with the animation effect is fully exemplified.

You have to copy thoses files in the corresponding drawable folder. Depending on the theme you use, dark or light you have a different set of icons.

In my case I simply copied the drawer_shadow.9.png and ic_drawer.png in the drawable folder and followed the example and everything works just fine.

The icons are available in the link I provided, but they are NOT in the "Action Bar Icon Pack", they are in the sample app in the corresponding res/drawable folders.

Share:
39,074

Related videos on Youtube

Jonik
Author by

Jonik

I'm a generalist software developer who's been programming professionally for 15+ years. Simplicity, code maintainability, easy deployments, automated testing, and continuous integration are some of the things close to my heart as a developer. I currently work as a freelance developer, focused on backend (Java/Scala/JVM mostly) and Android development. Enjoying Kotlin and Jetpack Compose nowadays especially! You can reach me by email through <jonik at iki dot country code for finland>.

Updated on July 09, 2022

Comments

  • Jonik
    Jonik almost 2 years

    At least Gmail and Youtube Android apps use a side menu (navigation drawer?) that opens by swiping, or by clicking the app icon (home button):

    enter image description here

    Is the menu indicator / icon in the screenshot above a ready-made part of Android SDK? (Or a custom icon Google uses in their apps?) In any case, what's the easiest way to get your home button to look like that, i.e., like it opens a menu?

    (targetSdkVersion 18; minSdkVersion 14)

    Resolution

    Finally got it working. What was missing for me was 1) the actual icon and 2) deferred call to syncState() on the ActionBarDrawerToggle.

    • hardartcore
      hardartcore over 10 years
      Are you going to use NavigationDrawer or you just want the same look as in the picture? The drawer indicator is a custom icon which not only Google uses to indicate that pressing home button from the ActionBar will open a menu.
    • Jonik
      Jonik over 10 years
      I'm already using NavigationDrawer and I want the same look as in the picture. :)
  • Jonik
    Jonik over 10 years
    I am already using NavigationDrawer. I'm looking for specific instructions on the easiest way to add that menu icon/indicator.
  • HpTerm
    HpTerm over 10 years
    As I said the example given in the link gives all the details. Simply copy paste the example and it works. Have you taken a look at the example given by android developper ? I can copy paste it here but everything is in the downloadable example.
  • Jonik
    Jonik over 10 years
    Ok, this is helpful. I already have ActionBarDrawerToggle with similar code; now I'm just looking for the right icon from the icon pack...
  • Jonik
    Jonik over 10 years
    Where exactly did you find the drawer_shadow.9.png / ic_drawer.png files? The Action Bar Icon Pack linked to in Navigation Drawer documentaion doesn't seem to contain such files.
  • HpTerm
    HpTerm over 10 years
    my mistake, they are in the "sample app" not in the action bar icon pack. If you download the sample app, go in the res/drawable folders. You'll find the icons there
  • Jonik
    Jonik over 10 years
    Any idea? There are no files named anything like "drawer" in the pack (find . -name "*drawer*.png" finds nothing).
  • hardartcore
    hardartcore over 10 years
  • Jonik
    Jonik over 10 years
    Thanks! I indeed found them in the sample app. (Though I'm not sure drawer_shadow.9.png is relevant in my case.) The indicator can be found here too: android-ui-utils.googlecode.com/hg/asset-studio/dist/…
  • Jonik
    Jonik over 10 years
    Great! That's what I needed. Can you edit that bit of info in the answer itself, and I'll accept it.
  • HpTerm
    HpTerm over 10 years
    Thanks for the feedback. I struggled a long time finding the icons and only found them in the sample app at the time I was looking for them. Thus, the link that @Android-Developer provided is useful.
  • Jonik
    Jonik over 10 years
    So, while this looks very promising, it's not enough to make the indicator show up, at least on my devices. :-/ I found a way to make it work on API 18+, but below that remains an open question...
  • hardartcore
    hardartcore over 10 years
    Check the edited answer.This code is tested on API LEVEL 14 and is working. If you are using Android Studio for development, you can create a new project with NavigationDrawer implemented and check the source code.
  • Jonik
    Jonik over 10 years
    Thanks for your efforts, I finally got it working. Curiously, mDrawerLayout.post(... mDrawerToggle.syncState(); ... ) was the crucial thing missing from my code! (I'm editing out some irrelevant bits from your answer to make it cleaner.)
  • rahstame
    rahstame over 10 years
    @Android-Developer : I have this similar problem, the 3 line icons is not animating when the drawer is opened: stackoverflow.com/questions/19829455/…
  • wal
    wal over 8 years
    are you supposed to call setUpDrawerToggle() from the activities onCreate? should mDrawerLayout and mDrawerToggle just be class variables of said Activity? (i will update code if so)