19

I'm using setDisplayHomeAsUpEnabled in order to show the arrow instead of the drawer "burger" icon but it's not getting animated or anything. Instead it shows the arrow drawable instantaneously.

Home screen: (Album 1)

When you tap a movie: (Album 2)

The thing is, the icon does the animation just fine when I slide the drawer, which makes me think that maybe I'm not supposed to use setDisplayHomeAsUpEnabled for this: (Album 3)

Album: http://imgur.com/a/LkXbh

Here's my drawer toggle code:

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

    drawerAdapter = new DrawerAdapter(this, App.getNavItems(), getSupportFragmentManager());
    drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawerList = (ExpandableListView) findViewById(R.id.left_drawer);

    // Set onGroupClick and onChildClick
    drawerAdapter.setClickEvents(MainActivity.this, drawerLayout, drawerList);
    drawerList.setAdapter(drawerAdapter);

    ActionBarDrawerToggle toolbarDrawerToggle = new ActionBarDrawerToggle(
            this,                 
            drawerLayout,        
            toolbar,             
            R.string.drawer_open, 
            R.string.drawer_close 
    ) {

        public void onDrawerClosed(View view) {
            super.onDrawerClosed(view);
            invalidateOptionsMenu();
        }

        public void onDrawerOpened(View view) {
            super.onDrawerOpened(view);
            invalidateOptionsMenu();
        }
    };
    drawerLayout.setDrawerListener(toolbarDrawerToggle);
    toolbarDrawerToggle.syncState();

EDIT: I want the animation not when opening the drawer, that works already. I would like to manually trigger the animation when I load a specific fragment. I may not have explained myself correctly.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Vextil
  • 191
  • 1
  • 1
  • 8

3 Answers3

79

I haven't tested this, but you may be able to achieve this by animating a float between 0 (drawer closed) and 1 (drawer open) and then passing the value into ActionBarDrawerToggle.onDrawerSlide(View, float). I believe that's how the toggle determines what state the animated toggle should be in.

Something like this should work.

ValueAnimator anim = ValueAnimator.ofFloat(start, end);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        float slideOffset = (Float) valueAnimator.getAnimatedValue();
        toolbarDrawerToggle.onDrawerSlide(drawerLayout, slideOffset);
    }
});
anim.setInterpolator(new DecelerateInterpolator());
// You can change this duration to more closely match that of the default animation.
anim.setDuration(500);
anim.start();
Nathan Walters
  • 4,116
  • 4
  • 23
  • 37
  • 22
    I cant, I need 15 reputation sorry :( – Vextil Oct 26 '14 at 20:56
  • 6
    This works perfectly. Just set start=0 and end=1 to go from hamburger to arrow, and start=1 and end=0 for arrow to hamburger. One thing you'll have to keep track of is when the drawer is closed when the arrow is shown. At this point, the hamburger ends up being shown (because of the drawer's slide), which you'll have to correct. – Raveesh Bhalla Nov 11 '14 at 05:50
  • This works prefectly when you click on the icon to open it and to close it. It also works when you slide the drawer either to open it or to close it. But, what I miss is the effect shown when you slide the drawer, i.e. the transition. How can I reproduce it? Here you can see the transition between hamburger to arrow https://www.youtube.com/watch?v=D8U-FKSrGVs, and here after implementing your solution https://www.youtube.com/watch?v=abvi8gHzHkU – joninx Jan 26 '15 at 14:35
  • @russellhoff if you post that as a new question with some of your code, I may be able to help you. – Nathan Walters Feb 04 '15 at 03:30
  • @NathanWalters here it's the question http://stackoverflow.com/questions/27187312/control-the-toolbar-icon-with-navigationdrawer. Thanks! – joninx Feb 04 '15 at 08:22
  • Works like a charm. Thank you. – Tejas Sherdiwala Jul 01 '15 at 07:37
  • 3
    @NathanWalters This works when going from back button to hamburger whilst using setDisplayHomeAsUpEnabled(false), but it doesn't work the other way around even if I swap 0, 1 start, end. Any idea how this could be done? – Eurig Jones Jul 09 '15 at 09:58
21

Since the question was asked, an alternative way has become available. The animated arrow is implemented by the now public class DrawerArrowDrawable which implements Drawable.

In your code, set the navigation icon as follows:

DrawerArrowDrawable drawerArrow = new DrawerArrowDrawable(this);
drawerArrow.setColor(myColor);

toolbar.setNavigationIcon(drawerArrow);

Register an OnBackStackChangedListener and animate the arrow manually:

@Override
public void onBackStackChanged() {
    boolean drawer = getSupportFragmentManager().getBackStackEntryCount() == 0;
    ObjectAnimator.ofFloat(drawerArrow, "progress", drawer ? 0 : 1).start();
}
Kirill Rakhman
  • 42,195
  • 18
  • 124
  • 148
  • Which is the class that has the onBackStackChanged() method? – Javier Delgado Mar 27 '16 at 22:27
  • The interface `OnBackStackChangedListener` has that method: http://developer.android.com/intl/es/reference/android/app/FragmentManager.OnBackStackChangedListener.html Used with http://developer.android.com/intl/es/reference/android/app/FragmentManager.html#addOnBackStackChangedListener(android.app.FragmentManager.OnBackStackChangedListener) – Kirill Rakhman Mar 28 '16 at 17:11
  • What's `drawer` in this case? – jlively Nov 11 '17 at 00:11
  • 1
    @jlively all the required code is included. `boolean drawer` indicates whether the drawable should display the hamburger or the back arrow. – Kirill Rakhman Nov 13 '17 at 09:47
0

Sounds like it's working as intended, you can use setDisplayHomeAsUpEnabled to simply enable the home button to be used as a back button, there is no animation.

If you're using a navigation drawer and want the animation don't use setDisplayHomeAsUpEnabled and for material theme (at least with AppCompat v21) make sure you use ActionBarDrawerToggle from the v7 package.

The Play Store is a good example. At the top level you have an activity with a nav drawer and a hamburger that animates when you open the drawer. If you tap on an app it opens a new activity that has a back arrow.

Philio
  • 3,675
  • 1
  • 23
  • 33
  • I have the material theme and the ActionBarDrawerToggle is the one from v7. Is there a way to change the icon to an arrow animating it programatically then? I want the animation not when opening the drawer, that works already. I would like to manually trigger the animation when I load a specific fragment. I may not have explained myself correctly. – Vextil Oct 26 '14 at 19:42
  • In that case you could use `setDisplayHomeAsUpEnabled(true)` and you would get a back arrow rather than a hamburger, but if you still have the nav drawer active then I don't think that's really as it's intended to work. If you check the Google apps that have been updated to the material theme you won't find any screens with a back arrow and an active nav drawer. – Philio Oct 26 '14 at 19:50
  • From a UX perspective, user expects: There is a hamburger = there is a nav drawer. There is a back arrow = go back to the previous screen. – Philio Oct 26 '14 at 19:51
  • That's true, and I understand that the user does not expect a drawer when there's an arrow. The thing is, my idea was to lock the drawer and show a back arrow because I wanted to avoid creating a new activity which allows me to transition the movie poster from the previous fragment into the new one with the new animation APIs and change the Toolbar background color smoothly. – Vextil Oct 26 '14 at 19:54
  • Sounds like that should work. Add new fragment, add to back stack, show back arrow, lock the drawer. Then when back is pressed change back to a hamburger and enable the drawer again. – Philio Oct 26 '14 at 19:59
  • There's still no way to animate the hamburger into an arrow right? – Vextil Oct 26 '14 at 20:03
  • 2
    @Philio "If you check the Google apps that have been updated to the material theme you won't find any screens with a back arrow and an active nav drawer." That's blatantly false. Click on an app in the Play Store to open its details activity: the back arrow is displayed, but you can still swipe in the nav drawer. Joaquin is asking how to trigger the hamburger->arrow animation manually. – Nathan Walters Oct 26 '14 at 20:04
  • Ah I see what you mean, I don't know of a way to animate the hamburger into a back arrow. – Philio Oct 26 '14 at 20:07
  • @Philio it works for me on both Play Games, Play Store, and Play Music. What version of Android are you running? – Nathan Walters Oct 26 '14 at 20:12
  • I restarted the phone and actually the nav drawer is working now as you suggested in all the Google apps. Strange! In fact in Play Music, it's messed up and when you're in a details activity you still get close animations and the hamburger jumps back to an arrow :) – Philio Oct 26 '14 at 20:15