Animate drawer icon into arrow on setDisplayHomeAs

2019-01-16 09:56发布

问题:

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.

回答1:

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();


回答2:

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


回答3:

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.