9
votes

I am having an issue with the toolbar and the back button. Here is the setup I have:

enter image description here

When I add a detail fragment, I animate the toolbar hamburger as outlined here. and this causes the hamburger to animate to an arrow.

Even in the comments section, a user mentions:

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.

But I cannot figure out how to get the back arrow to function properly. When I press the back arrow, the drawer opens and the detail fragment does not pop. How should I go about implementing this?

Questions

  • How should I animate hamburger to back arrow when adding a detail fragment? assuming the linked solution is not good enough.
  • How do I override the back arrow to perform only specific functions I wish? like animate to hamburger, pop back stack and NOT open the drawer.
2
well-versed question, +1 for you broZaffar Saffee

2 Answers

3
votes

After several hours of searching and playing around, I was able to build a solution that delivered on each requirement. Sources: 1,2

detailFragmentActive = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    setSupportActionBar(mToolbar);
    ...
    mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(detailFragmentActive) {
                        onBackPressed();
                        //if(displayBackAgain)
                        //return; //return after so you don't call syncState();
                    }else if (mDrawerLayou.isDrawerOpen(GravityCompat.START))
                        mDrawerLayout.closeDrawer(GravityCompat.START);
                    else
                        mDrawerLayout.openDrawer(GravityCompat.START);

                    mDrawerToggle.syncState();
                }
            });
}

private void animateHamburger(boolean isArrow){
        int start = 0, end = 1;

        if(isArrow){
            detailFragmentActive = false;
            start = 1; end = 0;
            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
        }else{
            detailFragmentActive = true;
            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        }
        ValueAnimator anim = ValueAnimator.ofFloat(start, end);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float slideOffset = (Float) valueAnimator.getAnimatedValue();
                mDrawerToggle.onDrawerSlide(mDrawerLayout, slideOffset);
            }
        });
        anim.setInterpolator(new DecelerateInterpolator());
        anim.setDuration(500);
        anim.start();
}

@Override
public void onBackPressed() {
    super.onBackPressed();
    animateHamburger(true);
}

public void onFragmentChange(){
    ...
    animateHamburger(false);
}
1
votes

You can set listener for this button:

toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (flagDeterminingAction) {
                drawerLayout.openDrawer(drawerListView);
            } else {
                onBackPressed();
               //or popbackstack or whatever you are using to going back in navigation
            }
        }