9

I'm swapping out the action bar for the tool bar, and I nearly have every piece of the puzzle in place. My issue is specifically if I navigate 'up' and restore the navigation drawer, the drawer toggle button no longer works. I figured out if I set the drawer mode to unlocked I have the ability to swipe to open the drawer, but can't click to open the drawer.

So I load fragment A, drawer behaviour is fine, go down to fragment B and apply the up icon, hit up to go back to A, and the drawer won't open with a click any more.

Entering Fragment B:

Toolbar t = mHostingActivity.getToolbar();
        mHostingActivity.getDrawerToggle().setDrawerIndicatorEnabled(false);
        mHostingActivity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        t.setNavigationIcon(mHostingActivity.getV7DrawerToggleDelegate().getThemeUpIndicator());
        t.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popBackStackToTop(mHostingActivity);
            }
        });

/**
 * Pop the back stack and hide the Up caret all the way to the top level of the {@link com.loylap.activities.MainActivity}
 *
 * @param activity our hosting activity
 */
public static void popBackStackToTop(MainActivity activity) {
    if (activity != null) {
        FragmentManager fm = activity.getSupportFragmentManager();
        fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        activity.getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
        activity.getDrawerToggle().setDrawerIndicatorEnabled(true);
    }
}

The navigation drawer is set up just like the sample, maybe the old way of setting up the options is the issue? For example, I still have this in my activity:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

EDIT:

Okay so I've narrowed down the issue to the setNavigationOnClickListener(). If I don't set this (and go up via back button) - the drawer behaves correctly. So now the question is how do I correctly allow the user to go 'up', and restore the click listener after to we do go up?

Daniel Wilson
  • 18,838
  • 12
  • 85
  • 135

5 Answers5

15

So I've figured out I was creating the wrong click listener. Instead of setNavigationOnClickListener(), I need setToolbarNavigationClickListener() :)

A subtle but important change, now the tool bar is behaving in partnership with the v7 ActionBarDrawerToggle

/**
 * Create the Up caret for a lower level fragment {@link com.loylap.activities.MainActivity}
 *
 * @param activity our hosting activity
 */
public static void createUpButton(final MainActivity activity)
{
    ActionBarDrawerToggle toggle = activity.getDrawerToggle();
    //Disables onClick toggle listener (onClick)
    toggle.setDrawerIndicatorEnabled(false);
    toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            popBackStackToTop(activity);
        }
    });

    Toolbar t = activity.getToolbar();
    t.setNavigationIcon(activity.getV7DrawerToggleDelegate().getThemeUpIndicator());
    activity.getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
}
Daniel Wilson
  • 18,838
  • 12
  • 85
  • 135
  • Just wanted to add a quick note to this, I've noticed onOptionsItemSelected is not fired in fragments, but seems fine for activities - where the standard android.R.id.home check can be made – Daniel Wilson Mar 24 '15 at 10:15
  • Thanks. I just modified your solution into a [simpler one](http://stackoverflow.com/a/30951016/1276636). – Sufian Jun 20 '15 at 06:31
7

In my case it was a matter of order, I needed to first set the toolbar and than set the on click listener. in this order:

       //works
    setSupportActionBar(myToolbar);

    myToolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            openDrawer(view);
        }
    });

rather than this:

    //doesn't work
    myToolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            openDrawer(view);
        }
    });
    setSupportActionBar(myToolbar);
Ezra Steinmetz
  • 1,267
  • 1
  • 17
  • 18
5

Inspired by the solution of Daniel Wilson but you only have to do it once and it is all set.

In my NavigationDrawer's setUp() (or you can do it anywhere you are initialising your ActionBarDrawerToggle instance), I write this code:

mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if(!mDrawerToggle.isDrawerIndicatorEnabled()) {
            getActivity().onBackPressed();
        }
    }
});

Now every time android.id.home is pressed and hamburger sign is not shown, the parent activity's onBackPressed() is called.

Sufian
  • 6,405
  • 16
  • 66
  • 120
0

I think you can't use:

     t.setNavigationIcon(mHostingActivity.getV7DrawerToggleDelegate().getThemeUpIndicator());
     t.setNavigationOnClickListener(new View.OnClickListener() ...

because it will break your normal navigation drawer behaviour.

Instead try something like this in onCreateOptionsMenu(Menu menu, MenuInflater inflater):

mHostingActivity.getDrawerToggle().setDrawerIndicatorEnabled(false);
mHostingActivity.getDrawerToggle().setHomeAsUpIndicator(mHostingActivity.getV7DrawerToggleDelegate().getThemeUpIndicator());

and then in onOptionsItemSelected

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:  
        popBackStackToTop(mHostingActivity);
        return true;

    default:
        break;
    }
    return false;
}

PS: don't forget to use setHasOptionsMenu(true); in your fragment onCreateView.

Daniel
  • 31
  • 1
  • 4
  • Hi Daniel, thanks for the input, that's actually the way it was originally. Several SO questions seem to have referenced the fact that R.id.home is no longer fired if you are using a tool bar which is a shame. I'm thinking now I need to remove any reference to the action bar drawer toggle and trigger drawer opening with a navigation click listener in the activity – Daniel Wilson Feb 04 '15 at 11:14
  • 1
    Hi, that is strange, because in my project I'm using toolbar and android.R.id.home is normally fired when I click on the arrow icon. But I can see, that you have found another solution so maybe I will be inspired next time :) – Daniel Feb 05 '15 at 10:34
0

To animate we can use.

ValueAnimator drawerAnimator = ValueAnimator.ofFloat(Constants.HAMBURGER, Constants.BACK);
drawerAnimator.addUpdateListener(drawerAnimationUpdateListener);
drawerAnimator.setDuration(Constants.DRAWER_ANIMATION_DURATION);
drawerAnimator.setInterpolator(new LinearInterpolator());

pass action 0 for HAMBURGER icon and 1 for BACK.

public void updateNavigationDrawer(int action) {
    drawerArrowDrawable = actionBarDrawerToggle.getDrawerArrowDrawable();
    if (action == Constants.BACK) {
        actionBarDrawerToggle.setDrawerIndicatorEnabled(false);
        actionBarDrawerToggle.setHomeAsUpIndicator(drawerArrowDrawable);
        actionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //onBackPress();
            }
        });
       drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED););
    } else {
        actionBarDrawerToggle.setDrawerIndicatorEnabled(true);
        drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
    }
    if (drawerArrowDrawable.getProgress() != action) {
        if (action == Constants.BACK) {
            drawerAnimator.start();
        } else {
            drawerAnimator.reverse();
        }
    }
}