9
votes

I had standart navigation drawer, but now i'm trying to modify it, using toolbar.

Earlier my code looked like: MainActivity.java

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

    Log.v("MAIN", "CREATE");
    initViews();
    setListeners();

    getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            shouldDisplayHomeUp();
        }
    });

    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getFragmentManager().findFragmentById(R.id.navigation_drawer);
    mTitle = getTitle();

    // Set up the drawer.
    mNavigationDrawerFragment.setUp(
            R.id.navigation_drawer,
            (DrawerLayout) findViewById(R.id.drawer_layout));
}

NavigationDrawerFragment.java

public void setUp(int fragmentId, DrawerLayout drawerLayout) {
    mFragmentContainerView = getActivity().findViewById(fragmentId);
    mDrawerLayout = drawerLayout;

    mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

    ((MainActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    ((MainActivity) getActivity()).getSupportActionBar().setHomeButtonEnabled(true);

    mDrawerToggle = new ActionBarDrawerToggle(getActivity(), mDrawerLayout,
            ((MainActivity) getActivity()).getToolbar(),
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close) {
        @Override
        public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);
            if (!isAdded()) {
                return;
            }

            getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }

        @Override
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            if (!isAdded()) {
                return;
            }

            if (!mUserLearnedDrawer) {
                // The user manually opened the drawer; store this flag to prevent auto-showing
                // the navigation drawer automatically in the future.
                mUserLearnedDrawer = true;
                SharedPreferences sp = PreferenceManager
                        .getDefaultSharedPreferences(getActivity());
                sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
            }
            if (mDrawerListView != null) {

            }
            getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }

        @Override
        public void onDrawerSlide(View drawerView, float slideOffset) {
            super.onDrawerSlide(drawerView, slideOffset);
        }
    };

    // If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
    // per the navigation drawer design guidelines.
    if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
        mDrawerLayout.openDrawer(mFragmentContainerView);
    }

    // Defer code dependent on restoration of previous instance state.

    mDrawerToggle.setDrawerIndicatorEnabled(true);

    mDrawerLayout.post(new Runnable() {
        @Override
        public void run() {
            mDrawerToggle.syncState();
        }
    });

    mDrawerLayout.setDrawerListener(mDrawerToggle);
}

Now i modified my code: MainActivity.java

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

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

    if (mToolbar != null) {
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

    initViews();
    setListeners();

    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getFragmentManager().findFragmentById(R.id.navigation_drawer);
    mTitle = getTitle();

    // Set up the drawer.
    mNavigationDrawerFragment.setUp(
            R.id.navigation_drawer,
            (DrawerLayout) findViewById(R.id.drawer_layout));


    shouldDisplayHomeUp();

    getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            mBackCount++;
            shouldDisplayHomeUp();
        }
    });
}

NavigationDrawerFragment.java

public void setUp(int fragmentId, DrawerLayout drawerLayout) {
    mFragmentContainerView = getActivity().findViewById(fragmentId);
    mDrawerLayout = drawerLayout;

    mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

    mDrawerToggle = new ActionBarDrawerToggle(getActivity(), mDrawerLayout,
            ((MainActivity) getActivity()).getToolbar(),
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close) {
        @Override
        public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);
            if (!isAdded()) {
                return;
            }

            getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }

        @Override
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            if (!isAdded()) {
                return;
            }

            if (!mUserLearnedDrawer) {
                // The user manually opened the drawer; store this flag to prevent auto-showing
                // the navigation drawer automatically in the future.
                mUserLearnedDrawer = true;
                SharedPreferences sp = PreferenceManager
                        .getDefaultSharedPreferences(getActivity());
                sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
            }
            if (mDrawerListView != null) {

            }
            getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }

        @Override
        public void onDrawerSlide(View drawerView, float slideOffset) {
            super.onDrawerSlide(drawerView, slideOffset);
        }
    };

    // If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
    // per the navigation drawer design guidelines.
    if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
        mDrawerLayout.openDrawer(mFragmentContainerView);
    }

    // Defer code dependent on restoration of previous instance state.

    mDrawerToggle.setDrawerIndicatorEnabled(true);

    mDrawerLayout.post(new Runnable() {
        @Override
        public void run() {
            mDrawerToggle.syncState();
        }
    });

    mDrawerLayout.setDrawerListener(mDrawerToggle);
}

And shouldDisplayHomeUp function:

public void shouldDisplayHomeUp (){
    boolean canBack = getFragmentManager().getBackStackEntryCount() > 0;
    mNavigationDrawerFragment.getDrawerToggle().setDrawerIndicatorEnabled(!canBack);
}

But the back arrow is not shown

I tried call

getSupportActionBar().setDisplayHomeAsUpEnabled(canBack);
getSupportActionBar().setHomeButtonEnabled(canBack);

So the back arrow appers but clicking on it has no effect

2
You want to change the back arrow when you have more than one fragment on your backstack?Pedro Oliveira
Yes, and provide back navigation instead opening drawerzagum
with actionbar this works perfectzagum

2 Answers

22
votes

From the docs:

To allow Up navigation with the app icon in the action bar, call setDisplayHomeAsUpEnabled():

@Override public void onCreate(Bundle savedInstanceState) {
     ...
     getActionBar().setDisplayHomeAsUpEnabled(true); }

This adds a left-facing caret alongside the app icon and enables it as an action button such that when the user presses it, your activity receives a call to onOptionsItemSelected(). The ID for the action is android.R.id.home.

This means that you will have to implement your back routine on onOptionsItemSelected and check for R.id.home. To avoid calling the routine when you click on the hamburger menu check for canback too on onOptionsItemSelected.

http://developer.android.com/training/implementing-navigation/ancestral.html#up

EDIT

To archieve what you want you will have to implement your own navigation routine.

    mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(shouldBack()) {
               //call onbackpressed or something
                if(displayBackAgain)
                    return; //return after so you don't call syncState();       
            }else if (mNavigationDrawerFragment.isDrawerOpen())
                mNavigationDrawerFragment.closeDrawer();
            else
                mNavigationDrawerFragment.openDrawer();
            mNavigationDrawerFragment.getActionBarDrawerToggle().syncState();
        }
    });
}

To enable the backbutton icon just call getSupportActionBar().setDisplayHomeAsUpEnabled(true); to disable it just call mNavigationDrawerFragment.getActionBarDrawerToggle().syncState();

3
votes

I found a way to control the back button and the nav. It worked with me. First , set up:

private void setupNav () {

    this.toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(this.toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    this.mActionBarDrawerToggle = new ActionBarDrawerToggle(this, this.mDrawerLayout, this.toolbar, 0, 0);

    this.mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //catch back button here.
        }
    });
    this.mDrawerLayout.setDrawerListener(this.mActionBarDrawerToggle);
    this.mActionBarDrawerToggle.syncState();
}

Important thing, this is the way I hide the hamburger and show the back button. You have to put this code in the place you want to show back button. I also lock the Nav when showing back button.

if (!isShowBackButton) {
        mActionBarDrawerToggle.setDrawerIndicatorEnabled(true);
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
    } else {

        mActionBarDrawerToggle.setDrawerIndicatorEnabled(false);
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        //enable back button
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }