Skip to content Skip to sidebar Skip to footer

Transition Animation From Hamburger To Arrow Icon On Adding Fragment

I have implemented master/detail flow and I would like to get transition animation from hamburger icon to arrow icon after adding fragment (the same animation as when opening navig

Solution 1:

Some explanations first.

  1. android.support.v7.app.ActionBarDrawerToggle uses special drawable class for hamburger-to-arrow icons and animation.

  2. the class is android.support.v7.graphics.drawable.DrawerArrowDrawable

  3. DrawerArrowDrawable implements animation with method setProgress(float progress), where progress is from 0 (hamburger) to 1 (arrow).

  4. ActionBarDrawerToggle uses private void setPosition(float position) that calls DrawerArrowDrawable.setProgress()

  5. ActionBarDrawerToggle uses public void onDrawerSlide(View drawerView, float slideOffset) to call private setPosition()

  6. ActionBarDrawerToggle calls toolbar.setNavigationOnClickListener() in constructor with it's listener, that is used to toggle drawer.

  7. ActionBarDrawerToggle keep track of actual DrawerArrowDrawable state. Toolbar and ActionBar do not track actual DrawerArrowDrawable state.

So, what you should do in activity. Option-A, use ActionBarDrawerToggle.

    // define a variable to track hamburger-arrow state
    protected boolean isHomeAsUp = false;

    protected DrawerLayout drawer;
    protected Toolbar toolbar;
    protected ActionBarDrawerToggle toggle;

    // I've implemented it in setContentView(), but you can implement it in onCreate()
    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        super.setContentView(layoutResID);

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

        drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        // overwrite Navigation OnClickListener that is set by ActionBarDrawerToggle
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (drawer.isDrawerOpen(GravityCompat.START)){
                    drawer.closeDrawer(GravityCompat.START);
                } else if (isHomeAsUp){
                    onBackPressed();
                } else {
                    drawer.openDrawer(GravityCompat.START);
                }
            }
        });
    }

    // call this method for animation between hamburged and arrow
    protected void setHomeAsUp(boolean isHomeAsUp){
        if (this.isHomeAsUp != isHomeAsUp) {
            this.isHomeAsUp = isHomeAsUp;

            ValueAnimator anim = isHomeAsUp ? ValueAnimator.ofFloat(0, 1) : ValueAnimator.ofFloat(1, 0);
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    float slideOffset = (Float) valueAnimator.getAnimatedValue();
                    toggle.onDrawerSlide(drawer, slideOffset);
                }
            });
            anim.setInterpolator(new DecelerateInterpolator());
            // You can change this duration to more closely match that of the default animation.
            anim.setDuration(400);
            anim.start();
        }
    }

Or you can set a DrawerArrowDrawable as a navigation icon with toolbar.setNavigationIcon() and animate it without ActionBarDrawerToggle See Option-B: https://stackoverflow.com/a/42024138/1148784


Solution 2:

See my another answer for explanation https://stackoverflow.com/a/42023946/1148784. This is option-B. code for Activity class. We do not use ActionBarDrawerToggle here.

    protected boolean isHomeAsUp = false;
    DrawerArrowDrawable homeDrawable;
    protected Toolbar toolbar;
    protected DrawerLayout drawer;

    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        super.setContentView(layoutResID);

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

        homeDrawable = new DrawerArrowDrawable(toolbar.getContext());
        toolbar.setNavigationIcon(homeDrawable);

        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (drawer.isDrawerOpen(GravityCompat.START)){
                    drawer.closeDrawer(GravityCompat.START);
                } else if (isHomeAsUp){
                    onBackPressed();
                } else {
                    drawer.openDrawer(GravityCompat.START);
                }
            }
        });
    }

    protected void setHomeAsUp(boolean isHomeAsUp){
        if (this.isHomeAsUp != isHomeAsUp) {
            this.isHomeAsUp = isHomeAsUp;
            ValueAnimator anim = isHomeAsUp ? ValueAnimator.ofFloat(0, 1) : ValueAnimator.ofFloat(1, 0);
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    float slideOffset = (Float) valueAnimator.getAnimatedValue();
                    homeDrawable.setProgress(slideOffset);
                }
            });
            anim.setInterpolator(new DecelerateInterpolator());
            anim.setDuration(400);
            anim.start();
        }
    }

Post a Comment for "Transition Animation From Hamburger To Arrow Icon On Adding Fragment"