1

I am using the ActionBarDrawerToggle with NavigationView. My content is displayed using fragments.

I am following this stackoverflow question to get the back button press to work but control never flows to onOptionsItemSelected.

This is my MainActivity.class:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.openDrawerContentDescRes, R.string.closeDrawerContentDescRes);
    mDrawerLayout.addDrawerListener(mDrawerToggle);
    mDrawerToggle.syncState();

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() == 0) {
        super.onBackPressed();
    } else {
        removeFragmentFromBackstack();
        updateToolbarWithHomeButton();
    }

}

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

    switch (item.getItemId()) {
        case android.R.id.home:
            // doesn't reach here ever.
            return true;
        case R.id.action_x:
            // do something
            return true;
        case R.id.action_y:
            // do something
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    // Sync the toggle state after onRestoreInstanceState has occurred.
    mDrawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mDrawerToggle.onConfigurationChanged(newConfig);
}

private void updateToolbarWithBackButton() {
    ActionBar actionBar = getSupportActionBar();
    if (null != mDrawerToggle && null != actionBar) {
        mDrawerToggle.setDrawerIndicatorEnabled(false);
        actionBar.setDisplayHomeAsUpEnabled(true);
    }
}

private void updateToolbarWithHomeButton() {
    ActionBar actionBar = getSupportActionBar();
    if (null != mDrawerToggle && null != actionBar) {
        actionBar.setDisplayHomeAsUpEnabled(false);
        mDrawerToggle.setDrawerIndicatorEnabled(true);
        mDrawerToggle.syncState();
    }
}

How can I capture the Back button <- click from Toolbar?


Update:

Thanks to @mike the back arrow button on the toolbar is now captured within the onOptionsItemSelected in my MainActivity code as updated below.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.openDrawerContentDescRes, R.string.closeDrawerContentDescRes);
    mDrawerLayout.addDrawerListener(mDrawerToggle);
    mDrawerToggle.syncState();

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() == 0) {
        super.onBackPressed();
    } else {
        removeFragmentFromBackstack();
        updateToolbarWithHomeButton();
    }

}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            //TODO: skip back press if fragment backstack count is 0.
            onBackPressed();
            updateToolbarWithHomeButton();
            return true;
        case R.id.action_x:
            // do something
            return true;
        case R.id.action_y:
            // do something
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    // Sync the toggle state after onRestoreInstanceState has occurred.
    mDrawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mDrawerToggle.onConfigurationChanged(newConfig);
}

private void updateToolbarWithBackButton() {
    ActionBar actionBar = getSupportActionBar();
    if (null != mDrawerToggle && null != actionBar) {
        mDrawerToggle.setDrawerIndicatorEnabled(false);
    }
}

private void updateToolbarWithHomeButton() {
    ActionBar actionBar = getSupportActionBar();
    if (null != mDrawerToggle && null != actionBar) {
        mDrawerToggle.setDrawerIndicatorEnabled(true);
        mDrawerToggle.syncState();
    }
}
Community
  • 1
  • 1

2 Answers2

2

If you want the onOptionsItemSelected() method to fire upon clicking the toggle, remove the toolbar argument from the ActionBarDrawerToggle constructor call.

mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
    R.string.openDrawerContentDescRes, R.string.closeDrawerContentDescRes);

Otherwise, the toggle handles opening and closing the drawer internally, and the call to ActionBarDrawerToggle#onOptionsItemSelected() isn't necessary.

If you want to handle clicking the home Button differently depending on the current state, you'll also want to remove the if block that returns at the top of the onOptionsItemSelected() method.

And, you should call setDisplayHomeAsUpEnabled(true) just once in onCreate(). You don't need to keep switching that on and off. Enabling and disabling the drawer indicator will take care of that.

Mike M.
  • 38,532
  • 8
  • 99
  • 95
  • I removed toolbar from new ActionBarDrawerToggle(this, mDrawerLayout, R.string.openDrawerContentDescRes, R.string.closeDrawerContentDescRes); but the switch case for MenuItem with id android.R.id.home does not pass. Is there a different id for Back button? – Kenneth Mascarenhas May 05 '16 at 08:05
  • The call to `mDrawerToggle.onOptionsItemSelected(item)` returns `true` when the `MenuItem`'s ID is `android.R.id.home`, so that `if` block is returning before execution reaches your `switch`. You can just move that call to your first `case`. – Mike M. May 05 '16 at 08:07
  • I've added a log statement inside the `if` block but it does not return true for `mDrawerToggle.onOptionsItemSelected(item)` when I click the back button – Kenneth Mascarenhas May 05 '16 at 08:14
  • What do you mean by back button, exactly? The toggle's arrow, or the `ActionBar`'s Up button? – Mike M. May 05 '16 at 08:20
  • When I add a new Fragment to my backstack, I execute `mDrawerToggle.setDrawerIndicatorEnabled(false);` and `actionBar.setDisplayHomeAsUpEnabled(true);` Now I get a button that looks like **←** which i think is the toggle's arrow. – Kenneth Mascarenhas May 05 '16 at 08:23
  • You should call `setDisplayHomeAsUpEnabled(true)` once in `onCreate()`. You don't need to keep switching that on and off. Enabling and disabling the drawer indicator will take care of that. – Mike M. May 05 '16 at 08:30
  • Did you understand what I mean? Move the `mDrawerToggle.onOptionsItemSelected(item)` call to your first `case`, remove the `if` block, call `setDisplayHomeAsUpEnabled(true)` in `onCreate()`, and remove the other two calls to `setDisplayHomeAsUpEnabled()` in your `updateToolbarWith*()` methods. – Mike M. May 05 '16 at 08:53
  • 1
    Thanks @Mike Setting `setDisplayHomeAsUpEnabled(true)` once in `onCreate` along with no `toolbar` in `ActionBarDrawerToggle`'s constructor worked in capturing `android.R.id.home` in the `onOptionsItemSelected`. – Kenneth Mascarenhas May 05 '16 at 08:54
  • Ah, good. I wasn't sure if I was clear. Glad you got it. Cheers! – Mike M. May 05 '16 at 08:56
0

Remove this line

 if (mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }

from onOptionsItemSelected() so it will look like this

@Override
public boolean onOptionsItemSelected(MenuItem item) {

switch (item.getItemId()) {
    case android.R.id.home:
        // doesn't reach here ever.
        return true;
    case R.id.action_x:
        // do something
        return true;
    case R.id.action_y:
        // do something
        return true;
    default:
        return super.onOptionsItemSelected(item);
}
}
N J
  • 27,217
  • 13
  • 76
  • 96