6

I'm currently updating a Fragment oriented app (I have one Activity with a FrameLayout container as host for all my Fragments) to Material Design. And I would like to animate the burger icon to the back arrow when replacing a Fragment.

Basically, if this wasn't clear enough, here is what I want to achieve. I don't want to use this library (MaterialMenu), I'd like to use the official AppCompat lib to the extend of possible.

I achieved this effect thanks to this solution, but I can't figure out how to make to ActionBarDrawerToggle as a back button when a Fragment is replaced.

So my questions is : should the back arrow icon still be the ActionBarDrawerToggleonce the Fragement has been replaced? In which case how do I override it so it acts like onBackPressed() instead of openning the drawer ? I already tried this but it doesn't work :

 @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        switch (item.getItemId())
        {
            case android.R.id.home:
                getActivity().onBackPressed();
                return true;
         }
         return false;
    }

Thanks in advance.

Community
  • 1
  • 1
MathieuMaree
  • 7,453
  • 6
  • 26
  • 31

3 Answers3

7

I think it's a little cleaner to track inside the drawer toggle if you've manually opened it or not. This is what I ended up doing:

public class ManualActionBarDrawerToggle extends ActionBarDrawerToggle {
    private static final float MENU_POSITION = 0f;
    private static final float ARROW_POSITION = 1.0f;

    private final int animationLength;
    private final DrawerLayout drawerLayout;
    private final Activity activity;
    private State currentState;

    private enum State { UP_ARROW, MENU }

    public ManualActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, int openDrawerContentDescriptionResource, int closeDrawerContentDescriptionResource) {
        super(activity, drawerLayout, openDrawerContentDescriptionResource, closeDrawerContentDescriptionResource);
        animationLength = activity.getResources().getInteger(android.R.integer.config_shortAnimTime);
        this.drawerLayout = drawerLayout;
        this.activity = activity;
        currentState = State.MENU;
    }

    public void animateToBackArrow() {
        ValueAnimator anim = ValueAnimator.ofFloat(MENU_POSITION, ARROW_POSITION);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            float slideOffset = (Float) valueAnimator.getAnimatedValue();
            onDrawerSlide(drawerLayout, slideOffset);
            }
        });

        anim.setInterpolator(new DecelerateInterpolator());
        anim.setDuration(animationLength);
        anim.start();

        currentState = State.UP_ARROW;
    }

    public void animateToMenu() {
        ValueAnimator anim = ValueAnimator.ofFloat(ARROW_POSITION, MENU_POSITION);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float slideOffset = (Float) valueAnimator.getAnimatedValue();
                onDrawerSlide(drawerLayout, slideOffset);
            }
        });

        anim.setInterpolator(new DecelerateInterpolator());
        anim.setDuration(animationLength);
        anim.start();

        currentState = State.MENU;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case (android.R.id.home):
                if (currentState == State.UP_ARROW) {
                    activity.onBackPressed();
                    return true;
                }
        }
        return super.onOptionsItemSelected(item);
    }
}
Gabriel
  • 2,279
  • 1
  • 20
  • 17
  • Don't forget to call activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); Before initializing everything – Udi Oshi May 25 '17 at 07:21
1

Menu drawable of this library has a method that can animate states:

If you want to switch from Burger to Arrow you do this call:

mMaterialMenu.animateState(IconState.ARROW);
Nikola Despotoski
  • 49,966
  • 15
  • 119
  • 148
  • Indeed, and as I said, I already used it but imo it's not as good looking than the stock icon :). – MathieuMaree Nov 04 '14 at 23:00
  • Then, why dont you switch to v7 ActionBarDrawerToggle? – Nikola Despotoski Nov 04 '14 at 23:02
  • Well, I did...? What I want is not the toggle animation while openning/closing the drawer; it's the same animation but when switching fragments. And I'd like the toggle to act like the home/back arrow once a Fragment is added – MathieuMaree Nov 04 '14 at 23:06
  • Use this http://developer.android.com/training/implementing-navigation/ancestral.html – xDragonZ Nov 05 '14 at 03:12
  • How can we keep default Menu Drawable to `X` state in xml. I am using in activity `mMaterialMenu.animateState(IconState.X);` to switch from default `Burger` Menu to `X` one. But it changes with animation. I didn't find any attribute to change state in xml. Please help. – Dory Dec 11 '14 at 09:45
  • I found what it is, instead of using `mMaterialMenu.animateState(IconState.X);` I should use `mMaterialMenu.setState(IconState.X);` from which I was able to change state from default `BURGER` to `X` without animation,though I didn't find any attribute to set in `xml`. – Dory Dec 11 '14 at 09:48
1

OK so I figured out a way. I'm pretty sure it's NOT a good solution as I'm using the ActionBarDrawerToggle for a different purpose than what it was created for.

But it works, so here's what I did. I simply created a custom ActionBarDrawerToggle in which I override the onOptionsItemSelected(...) method :

class MyDrawerToggle extends ActionBarDrawerToggle
{
    // ... Default constructors matching super go here

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        // If the back stack isn't empty, ie if I'm not in a Fragment 
        // accessible from the NavigationDrawer, I simulate the onBackPressed behaviour
        if (getFragmentManager().getBackStackEntryCount() != 0)
        {
            onBackPressed();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

If anyone has a better solution, please feel free to propose.

MathieuMaree
  • 7,453
  • 6
  • 26
  • 31