1

I'm using the v7.widget.Toolbar in my app, but I'm getting some funky functionality. I have my main activity and fragments that are placed over it. When there are no fragments on the backStack, the hamburger button shows and the menu works correctly. When I add a fragment to the backStack, the up caret shows correctly, however when I click the up caret, the nav menu opens instead of the fragment being popped off the stack.

Now if there's a real answer, I'll take it, but at this point I will take a hackish solution. I tried adding a listener so I knew when the action bar button was hit, but that just made it so the fragment popped, the page went back, but the nav menu still opened. onOptionsItemSelected is not being called (due to the way I implemented the Drawer Toggle, but doing it the "correct" way gave me way more problems, such as no nav menu showing on the main page at all).

To sum it up for clarity: The up caret is opening the nav menu, instead of going back.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mTitle = getTitle();
    toolbar = (Toolbar) findViewById(R.id.tool_bar); // Attaching the layout to the toolbar object
    frameLayout = (FrameLayout) findViewById(R.id.frame_layout);
    setSupportActionBar(toolbar);

    //Listen for changes in the back stack
    getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            shouldDisplayHomeUp();
        }
    });

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    mDrawerContent = findViewById(R.id.drawer_content);
    mDrawerList = (ListView) findViewById(R.id.drawer_list);

    mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
    mDrawerList.setAdapter(new DrawerListItemAdapter(DRAWER_ITEMS, getApplicationContext()));

    mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.openDrawer, R.string.closeDrawer) {

        public void onDrawerClosed(View view) {
            invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
        }

        public void onDrawerOpened(View drawerView) {
            invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            Log.d("Main", "Open Menu");
        }

    };
    mDrawerToggle.syncState();
    mDrawerLayout.setDrawerListener(mDrawerToggle);
}

    @Override
public void onBackStackChanged() {
    shouldDisplayHomeUp();
}

public void shouldDisplayHomeUp(){
    //Enable Up button only if there are entries in the back stack
    boolean canback = getSupportFragmentManager().getBackStackEntryCount()>0;
    ActionBar ab = getSupportActionBar();
    if(ab != null){
        ab.setDisplayHomeAsUpEnabled(canback);
    }
    if(!canback){
        //App can crash as mDrawerToggle will be null when app launches
        try{
            mDrawerToggle.syncState();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    Log.d("Main", "shouldDisplayHomeUp");
}

@Override
public boolean onSupportNavigateUp() {
    //This method is called when the up button is pressed. Just the pop back stack.
    Log.d("Main", "Up carat pressed");
    getSupportFragmentManager().popBackStack();
    return true;
}

@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);
    // Pass any configuration change to the drawer toggls
    mDrawerToggle.onConfigurationChanged(newConfig);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();
    Log.d("Main", "Menu item clicked: " + Integer.toString(item.getItemId()));
    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

The solution that worked for me

A combination of Alex' answer (including his comment in the answer) below and this hacky answer.

Community
  • 1
  • 1
Will Nasby
  • 1,068
  • 2
  • 16
  • 39

1 Answers1

1

You can use setToolbarNavigationClickListener() - it sets the listener that handles clicks when drawer indicator is disabled

drawerToggle.setToolbarNavigationClickListener((View view) -> {
        getSupportFragmentManager().popBackStack();
    });
Alex
  • 473
  • 1
  • 10
  • 19
  • `mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d("Main", "setToolbarNavClickListener"); getSupportFragmentManager().popBackStack(); } });` Is what I did, however it's never called. Not on the main screen with the correct nav menu or the fragment-deep screen with the up caret. – Will Nasby Mar 16 '16 at 16:37
  • listener only works if you use `mDrawerToggle.setDrawerIndicatorEnabled(boolean)` - try this instead of `ab.setDisplayHomeAsUpEnabled(canback);` – Alex Mar 16 '16 at 17:25
  • The up caret doesn't show on some pages, but when it does it works properly. I'd call that progress. I'll post back if I figure out how to get it to show on all pages. I currently only have the "setDrawerIndicatorEnabled()" method where the "setDisplayHomeAsUpEnabled()" was previously. – Will Nasby Mar 16 '16 at 17:40