I have two navigation fragments in the DrawerLayout. One navigation fragment in on the left and second is on the right.
In some cases I need to open left navigation fragment and lock it.
When I had only left navigation fragment I used drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
But when I have added second navigation fragment on the right, this method started to open and lock both panels.
How to open and lock only left navigation view in this case?
Change you code like this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drawer_layout);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mLeftDrawerList = (ListView) findViewById(R.id.left_drawer);
mRightDrawerList = (ListView) findViewById(R.id.right_drawer);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,R.drawable.ic_drawer, R.string.drawer_open,R.string.drawer_close) {
public void onDrawerOpened(View view){
if(view.equals(mRightDrawerList)) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mLeftDrawerList);
} else {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mRightDrawerList);
}
invalidateOptionsMenu();
}
public void onDrawerClosed(View view) {
if(view.equals(mRightDrawerList)) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, mLeftDrawerList);
} else {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, mRightDrawerList);
}
invalidateOptionsMenu();
}
});
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
This should work.
Related
I'm currently struggling with the DrawerLayout animation doing weird stuff; The hamburger icon is laggy and often switch from hamburger to arrow without animation if I don't put an Handler to delay the fragment transaction animation.
So I ended up putting an handler to wait until the hamburger icon perform the animation but it just doesn't feel natural that we need to wait until the drawer close to switch fragment. I'm sure there is a better way to handle this...
Here is how I do currently:
private void selectProfilFragment() {
final BackHandledFragment fragment;
// TODO test this again
Bundle bundle = new Bundle();
bundle.putString(FragmentUserProfile.USER_FIRST_NAME, user.getFirstname());
bundle.putString(FragmentUserProfile.USER_LAST_NAME, user.getLastname());
bundle.putString(FragmentUserProfile.USER_PICTURE, user.getProfilepic());
bundle.putString(FragmentUserProfile.USER_EMAIL, user.getEmail());
bundle.putBoolean(FragmentUserProfile.USER_SECURITY, user.getParameters().getSecuritymodule().equals("YES"));
fragment = new FragmentUserProfile();
fragment.setArguments(bundle);
mDrawerLayout.closeDrawer(mDrawerLinear);
new Handler().postDelayed(new Runnable() {
public void run() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.pull_in_right, R.anim.push_out_left, R.anim.pull_in_left, R.anim.push_out_right);
ft.replace(R.id.content_frame, fragment)
.addToBackStack(fragment.getTagText())
.commitAllowingStateLoss();
}
}, 300);
}
It's still glitching a little bit in between the DrawerLayout closing and opening fragment transaction animation.
Here is How I instanciate the drawer:
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mDrawerListChild.setAdapter(new DrawerListAdapter(this, R.layout.drawer_layout_item, mPlanTitles));
mDrawerListChild.setOnItemClickListener(new DrawerItemClickListener());
mProfilPic.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectProfilFragment();
}
});
mDrawerToggle = new ActionBarDrawerToggle(
this,
mDrawerLayout,
toolbar,
R.string.drawer_open,
R.string.drawer_close
) {
public void onDrawerClosed(View view) {
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
invalidateOptionsMenu();
}
};
getSupportFragmentManager().addOnBackStackChangedListener(mOnBackStackChangedListener);
mDrawerLayout.setDrawerListener(mDrawerToggle);
setSupportActionBar(toolbar);
I am not sure what causing this behavior though I want to draw your attention on few thing.
I am not aware which ActionBarDrawerToggle class you are using but preferable to use android.support.v7.app.ActionBarDrawerToggle instead of android.support.v4.app.ActionBarDrawerToggle as it is deprecated.
Use addDrawerListener() instead of setDrawerListener() as it is deprecated.
Use spinBars and set value true to rotate bars during transition.
e.x. in your styles.xml as described here.
In onDrawerClosed and onDrawerOpened call syncState(). Also call this method on your ActionBarDrawerToggle. Check this.
Hope this will help you.
Heres how you can do it. In the Activity containing fragment setup your drawer.
public void setupDrawer(){
NavigationFragment drawerFragment = (NavigationFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
mActionbarToggle = drawerFragment.setUp(R.id.navigation_drawer, mDrawerLayout, mToolbar);
}
Now in the NavigationDrawerFragment define your setUp method
public ActionBarDrawerToggle setUp(int navigation_drawer, DrawerLayout drawerLayout, Toolbar mToolbar) {
mFragmentContainerView = getActivity().findViewById(navigation_drawer);
this.mDrawerLayout = drawerLayout;
//mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
mDrawerToggle = new ActionBarDrawerToggle(getActivity(), drawerLayout, mToolbar, R.string.drawer_open, R.string.drawer_close) {
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
if (!isAdded()) {
return;
}
getActivity().supportInvalidateOptionsMenu(); // calls onPrepareOptionsMenu()
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
if (!isAdded()) {
return;
}
getActivity().supportInvalidateOptionsMenu(); // calls onPrepareOptionsMenu()
}
};
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity) mContext).onBackPress();
}
});
mDrawerLayout.post(new Runnable() {
#Override
public void run() {
mDrawerToggle.syncState();
}
});
mDrawerLayout.setDrawerListener(mDrawerToggle);
return mDrawerToggle;
}
That's it, your drawer is completely setUp.
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.
You can use setToolbarNavigationClickListener() - it sets the listener that handles clicks when drawer indicator is disabled
drawerToggle.setToolbarNavigationClickListener((View view) -> {
getSupportFragmentManager().popBackStack();
});
I am using DrawerToggle with toolbar in my project. I have a requirement to make drawer toggle in active (i.e it should not open or close on click or swipe). But I am completely struct how to achieve the things by making the toggle event standstill. I know that my question is quite different but my requirement is to control dynamically on a runtime to control the property of drawertoggle.
I am also posting piece of code I am using for drawertoggle in my project for your reference
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawer_layout);
findViews();
createFragments ();
materialColorNames = getResources ().getStringArray(R.array.color_names);
drawerAdpater = new DrawerAdapter(this,materialColorNames);
mDrawerList.setAdapter(drawerAdpater);
if (toolbar != null) {
changeTitleText ("Droid");
toolbar.setTitleTextColor (getResources ().getColor (R.color.droid_white));
setSupportActionBar (toolbar);
}
initDrawer();
updateFragment (0);
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
}
#Override
protected void onResume () {
super.onResume ();
}
private void changeTitleText (CharSequence title) {
toolbar.setTitle(title);
}
private void createFragments () {
myProjectsFragment = new MyProjectsFragment();
}
private void findViews() {
mDrawerList = (ListView) findViewById(R.id.left_drawer);
toolbar = (Toolbar) findViewById(R.id.toolbar);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
}
private void initDrawer() {
drawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
// mDrawerLayout.closeDrawer(mDrawerList);
}
};
mDrawerLayout.setDrawerListener(drawerToggle);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
private void updateFragment(int position) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
switch (position) {
case 0:
ft.replace(R.id.content_frame, myProjectsFragment);
break;
}
Kindly please help me with this solution. I am seraching this to be done for the long time. Thanks in advance. Please let me know through comments if my question is not clear.
In your onCreate() after drawer layout and list are found call:
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mDrawerList);
drawerToggle.setDrawerIndicatorEnabled(false);
From the Javadoc:
public void setDrawerLockMode (int lockMode, View drawerView)
Enable or disable interaction with the given drawer.
This allows the application to restrict the user's ability to open or close the given drawer. DrawerLayout will still respond to calls to openDrawer(int), closeDrawer(int) and friends if a drawer is locked.
I'm currently using within my app the android.support.v7.widget.Toolbar and android.support.v4.widget.DrawerLayout. Everything is working right, but there is a slight thing I want to change its behaviour.
When I open the drawer, the whole drawer occupies the space of the Toolbar. It would be nice that the Toolbar stays on top, like in the Google Music app. How can I achieve that?
But the most important thing isn't the previous. At first, the icon which is loaded in the application is the three stripped one. I've realised that after opening the drawer, the icon changes to an arrow. And after loading a fragment, the arrow remains there as the Toolbar icon, even if I press back until the first screen. How could I avoid the arrow appearing from after opening the drawer? I'd want to change this icon manually, specially when I load lower level fragments.
Thanks for your help!
Code:
public class HomeActivity extends BaseActivity {
...
private DrawerLayout mDrawer;
private ActionBarDrawerToggle mDrawerToggle;
private ListView mDrawerList;
private ListView mDrawerRightList;
private RelativeLayout mDrawerRelativeLayout;
private String[] mDrawerMenuTitles;
private Toolbar mToolbar;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDrawerMenuTitles = getResources().getStringArray(R.array.main_menu_options);
mDrawer = (DrawerLayout) findViewById(R.id.drawer);
mDrawerRelativeLayout = (RelativeLayout) findViewById(R.id.theDrawerRelativeLayout);
mDrawer.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mDrawerRightList = (ListView) findViewById(R.id.theDrawerRight);
mDrawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mDrawerRightList);
mDrawerList = (ListView) findViewById(R.id.theDrawer);
mDrawerList.setAdapter(new ArrayAdapter<String>(
getSupportActionBar().getThemedContext(),
R.layout.drawer_list_item,
mDrawerMenuTitles
));
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
setmToolbar((Toolbar) findViewById(R.id.toolbar));
mDrawerToggle = new ActionBarDrawerToggle(
this,
mDrawer,
mToolbar,
R.string.drawer_open,
R.string.drawer_close){
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
// TODO Auto-generated method stub
super.onDrawerSlide(drawerView, slideOffset);
}
#Override
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
//getSupportActionBar().setTitle(CURRENT_FRAGMENT);
}
/** Called when a drawer has settled in a completely open state. */
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
//getSupportActionBar().setTitle("ConfiguraciĆ³n");
}
};
mDrawerToggle.setDrawerIndicatorEnabled(true);
mDrawerToggle.syncState();
mDrawer.setDrawerListener(mDrawerToggle);
setToolbarSubtitle(getString(R.string.misrutas_titulo));
initialisePreferences(savedInstanceState);
if (savedInstanceState == null) {
replaceFragment(DEFAULT_FRAGMENT);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
mDrawer.openDrawer(GravityCompat.START);
return true;
}
return super.onOptionsItemSelected(item);
}
private class DrawerItemClickListener implements OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//selectItem(position);
final int thePos = position;
mDrawer.setDrawerListener( new DrawerLayout.SimpleDrawerListener(){
#Override
public void onDrawerClosed(View drawerView){
....
}
});
if(mDrawer.isDrawerOpen(GravityCompat.START))
mDrawer.closeDrawer(mDrawerRelativeLayout);
}
}
#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 void onBackPressed(){
setToolbarSubtitle(getString(R.string.app_name_subtitle));
if (getSupportFragmentManager().getBackStackEntryCount() == 1){
finish();
}
else {
super.onBackPressed();
}
}
private void replaceFragment (String to){
if(!to.equalsIgnoreCase(CURRENT_FRAGMENT)){
CURRENT_FRAGMENT = to;
Fragment fragment = Fragment.instantiate(HomeActivity.this, to);
String backStateName = fragment.getClass().getName();
String fragmentTag = backStateName;
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped && manager.findFragmentByTag(fragmentTag) == null){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment, fragmentTag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(backStateName);
ft.commit();
}
}
}
//More methods
....
}
EDIT:
I have been able to modify a little bit my layout, so that the Toolbar stays on top of the rest screen (drawer and fragment). But I haven't been able to control the icon. When I open the drawer, the hamburger icon converts into the arrow. When I close the drawer, the arrow is converted into the hamburger. But when I press an option within the drawer, a new fragment is inflated and the hamburger icon is replaced by the arrow until the application is closed, so that the hamburger icon is never seen.
How can I adapt the icon behaviour so that it doesn't change from hamburger to arrow when I click over a drawer option?
now I try to do a similiar navigation drawer as you...
Basically respect me is that I had a diferent package for navigation drawer that I think so is different from your navigation drawer... My package is:
//From android studio
compile 'com.android.support:appcompat-v7:21.0.0'
I don't know if this can help you, but I follow this greatest tutorial and my navigation drawer work it's similar as you wish!
http://androideity.com/2013/12/16/android-navigation-drawer-parte-1/
http://androideity.com/2014/02/26/android-navigation-drawer-parte-2/
I wait that I help you! Good luck!
PD: If you have a problems with this tutorial or same advice me! :D
At first glance seems that you are setting new drawer listener whenever item is selected, precisely in this snippet:
private class DrawerItemClickListener implements OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//selectItem(position);
final int thePos = position;
mDrawer.setDrawerListener( new DrawerLayout.SimpleDrawerListener(){
#Override
public void onDrawerClosed(View drawerView){
....
}
});
if(mDrawer.isDrawerOpen(GravityCompat.START))
mDrawer.closeDrawer(mDrawerRelativeLayout);
}
}
This snippet replaces ActionBarDrawerToggle (which implements DrawerListener as well), so no calls are made to ActionBarDrawerToggle which controls the icon.
How can I adapt the icon behaviour so that it doesn't change from hamburger to arrow when I click over a drawer option?
Relating to your previous statements, this sound vague to me. Why you'd be preventing this default behaviour? You can prevent morphing by not calling super calls in DrawerListener's methods.
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
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();
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);
}