I'm working with Navigation Drawer and I want to click the button on activity and Navigation Drawer should show, but I don't know how to do it. Normally, when we swipe from left edge to the right the navigation will be shown. as such, I want to be able to open the navigation drawer with the click of a button.
Use the following methods to open and close your navigation drawer:
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
//To Open:
drawerLayout.openDrawer(Gravity.START);
//To Close:
drawerLayout.closeDrawer(Gravity.END);
Source1 for more information:
Source2
Button hamMenu = findViewById(R.id.ham_menu);
hamMenu.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DrawerLayout navDrawer = findViewById(R.id.drawer_layout);
// If the navigation drawer is not open then open it, if its already open then close it.
if(!navDrawer.isDrawerOpen(GravityCompat.START)) navDrawer.openDrawer(Gravity.START);
else navDrawer.closeDrawer(Gravity.END);
}
});
You can also use a method and Use the exact same steps given by #Zeeshan.
public void hamMenu(View view){
DrawerLayout drawer = findViewById(R.id.drawer_layout);
if (!drawer.isDrawerOpen(GravityCompat.START)) {
drawer.openDrawer(GravityCompat.START);
} else {
drawer.closeDrawer(GravityCompat.END);
}
}
Use this method in the button which you need android:Onclick="hamMenu" in .xml.
when i set lock and disable swipe on open and close drawer layout i cant close that by pressing on back button on the phone, when mode is not lock pressing back button cause of close that but when i change mode to for example :
drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
pressing back button couldn't close that
You need to close it programmatically because drawer is in lock mode and this will not be automatically close.
Implement this method in your activity so that you can close it with programmatically.
See the documentation of DrawerLayout.LOCK_MODE_LOCKED_CLOSED
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}else{
super.onBackPressed();
}
}
I think this is because you set the state to LOCKED_CLOSED so you cannot move from this state until you set it to the _UNLOCKED state. Check my answer here: https://stackoverflow.com/a/50304856/2873702
Basically you have to recall the function
drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
with the UNLOCKED parameter instead. I suggest to try using it in the onBackPressed function. You should do something like
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
drawer.closeDrawer(GravityCompat.START);
drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
}else{
super.onBackPressed();
}
}
I found out, that I can turn on the back arrow with
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
but when I click on the arrow the drawer opens instead of going to the first Fragment.
How can I turn off the AppDrawer inside a Fragment and turning it on again when in first Fragment?
With the following lines of code when you back press first time then if your drawer opened then first it will close then on second back press you will go on previous activity.
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {//this is check drower is open or not
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();//or you can redirect to the another activity
}
}
I know similar questions have been asked before but is there any clear easy to understand example to do this. What I usually do is create a project from Android Studio and select the one with navigation on it. But after I call my next activity it does not have the navigation drawer anymore. All I can do is just add a back button to the main activity in the toolbar. All I want is to have the ability to call the navigation drawer from all my activitie even those with a back button on the toolbar.
Is there a best practice to make the navigation drawer menu callable which is applicable to different scenarios. For example
main activity with drawer -> 2nd activity with toolbar but has back button. How do you call the drawer menu?
main activity with drawer -> 3rd activity with no toolbar. call navigation drawer thru swipe or buttons?
Basically Each Activity has its own actionBar and each actionbar can use own Navigation Drawer. So If You want to same navigation Drawer. You can use Fragment. You can make MainActivity has Navigation Drawer and Use FrameLayout in Mainactivity Then Replace Fragment. if You want each Activity has single Navigation Drawer. it is not Possible.
simply you can achieve that by having a base activity that you can extend from any activity that you want it to have the DL. for example
public abstract class SampleBaseActivity extends AppCompatActivity {
protected abstract boolean isHome();
private DrawerLayout drawerLayout;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawer_layout);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
android.support.v7.widget.Toolbar toolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
if (!isHome()) {
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_back);
} else {
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
#Override public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
if (isHome()) {
drawerLayout.openDrawer(GravityCompat.START);
} else {
onBackPressed();
}
return true;
}
return super.onOptionsItemSelected(item);
}
}
now in every activity you like to have the drawer extend this activity instead of the normal AppCompatActivity
The setup
I have an activity whose contentView is an instance of a DrawerLayout, which has a navigation drawer with a drawer indicator displayed in the action bar. The activity contains a Fragment, let's call it ListFragment, which contains a list of options. When an option is clicked, I replace the ListFragment with a DetailFragment.
At this point, I would like to display an "up" navigation option instead of the navigation drawer indicator. I'm able to display the "up" icon if I disable the drawer indicator by calling mDrawerToggle.setDrawerIndicatorEnabled(false), but this only removes the drawer icon--it does not remove the functionality--that is, when I click the caret, the navigation drawer is still opened.
Additionally, in these subviews, I would like to disable the opening of the drawer by dragging from the edge of the screen. I have tried doing this by calling setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) but it doesn't seem to have disabled this functionality.
I have tried extending the ActionBarDrawerToggle class to prevent opening the drawer when the indicator is clicked--however, all that happens is that the overriding action (the "up" navigation) is performed, but the drawer still opens.
I have also implemented the steps in Switching between Android Navigation Drawer image and Up caret when using fragments . It works insofar as displaying the caret goes, but despite overriding the up button functionality, the menu still opens (the app does navigate back--it just also opens the drawer).
Question
So, long story short: is there any (preferably clean and elegant, but at this point I'll go with hacky) way to achieve these things when my layout root is a DrawerLayout:
Replace the drawer indicator with an "up" caret (tentatively doable via mDrawerToggle.setDrawerIndicatorEnabled(false))
Prevent the drawer from opening when the caret is clicked, and instead override with my own "up" functionality
Prevent the drawer from opening when I drag from the edge of the screen.
Edit
All right, it looks like if I both override ActionBarDrawerToggle AND onOptionsItemSelected, the menu does not open when I click the caret. But it still opens if I drag from the edge. Help!
Short Code
public void setDrawerState(boolean isEnabled) {
if ( isEnabled ) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
drawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_UNLOCKED);
drawerToggle.setDrawerIndicatorEnabled(true);
drawerToggle.syncState();
}
else {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
drawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
drawerToggle.setDrawerIndicatorEnabled(false);
drawerToggle.syncState();
}
}
This is only part of the solution that I arrived at, but it was quite hard to figure out this bug, so I'm leaving this here for posterity's sake.
This how I was defining the ListView for my navigation drawer:
<ListView
android:id="#+id/listview_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start|bottom"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
Even after calling setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) I was still able to slide the drawer open.
However, after changing the layout_gravity to "start" this problem seems to be resolved.
I was able to reproduce this issue in a sample, navigation-drawer-only app, so it does appear to be a reproducible issue not unique to my situation.
Building on sonida's answer. After calling setDrawerIndicatorEnabled(false), onNavigateUp wasn't being called still. So, I just created a new onClickListener that called it:
public void setDrawerState(boolean isEnabled) {
if ( isEnabled ) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
drawerToggle.setDrawerIndicatorEnabled(true);
drawerToggle.syncState();
}
else {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
drawerToggle.setDrawerIndicatorEnabled(false);
drawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onSupportNavigateUp();
}
});
drawerToggle.syncState();
}
}
also I think
drawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_UNLOCKED);
has been depreciated, but it works fine without it.
You need to disable swipe and disable the actionbar home button:
Use the below code that builds on the code already given to disable swipe
public void setDrawerState(boolean isEnabled) {
if ( isEnabled ) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
mDrawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_UNLOCKED);
mDrawerToggle.setDrawerIndicatorEnabled(true);
mDrawerToggle.syncState();
getActivity().getActionBar().setHomeButtonEnabled(true);
}
else {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
mDrawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
mDrawerToggle.setDrawerIndicatorEnabled(false);
mDrawerToggle.syncState();
getActivity().getActionBar().setHomeButtonEnabled(false);
}
}
Building on answer by #sonida And after using the tweaks given by #luca992 and #jai.
I tried above suggested codes But the "up" or "Back" arrow in left side of action bar was just not showing up in my app. But luckily I was able to fix that.
I had to add this extra line of code in setNavigationDrawerState() [Ref: android.support.v7.app.ActionBarDrawerToggle.setHomeAsUpIndicator ]
toggle.setHomeAsUpIndicator(R.drawable.ic_keyboard_backspace_white_24dp);
I downloaded the drawable: ic_keyboard_backspace_white_24dp from Material.io
Here is the complete code:
MainActivity.java -> onCreate()
DrawerLayout drawer;
ActionBarDrawerToggle toggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Start: Code automatically generated by Android Studio
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
// End: Code automatically generated by Android Studio
// I had to add this listener as the "back" arrow was totally unresponsive
// Thanks to #luca992
toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
// Start: Code automatically generated by Android Studio
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
// End: Code automatically generated by Android Studio
// More custom code for other stuff
// ...
}
MainActivity.java -> setNavigationDrawerState()
public void setNavigationDrawerState(boolean isEnabled) {
if ( isEnabled ) {
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
toggle.setDrawerIndicatorEnabled(true);
toggle.syncState();
}
else {
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
toggle.setDrawerIndicatorEnabled(false);
// the extra line of code goes here
toggle.setHomeAsUpIndicator(R.drawable.ic_keyboard_backspace_white_24dp);
toggle.syncState();
}
MainActivity.java -> onBackPressed()
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if(getSupportFragmentManager().getBackStackEntryCount() > 0){
getSupportFragmentManager().popBackStack();
}else {
super.onBackPressed();
}
}
MainActivity.java -> startFragment() [dummy function for example]
public void startFragment(){
MyFrag myFrag = new MyFrag();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frag_container ,myFrag)
.addToBackStack(null)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.commit();
}
MyFrag.java --> onViewCreated()
#Override
public void onViewCreated (View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
// Say, using an implemented interface Make call to MainActivitiy's setNavigationDrawerState() passing false
// setNavigationDrawerState(false)
// ...
}
MyFrag.java --> onDestroyView()
#Override
public void onDestroyView(){
// Say, using an implemented interface Make call to MainActivitiy's setNavigationDrawerState() passing true
// setNavigationDrawerState(true)
super.onDestroyView();
}