How to detect that the DrawerLayout started opening?
Solution 1
DEPRECATED: See other answers for a more suitable solution
There are 2 possible ways to do that:
- Use
onDrawerSlide(View drawerView, float slideOffset)
callback
slideOffset
changes from 0 to 1. 1
means it is completely open, 0
- closed.
Once offset changes from 0
to !0
- it means it started opening process. Something like:
mDrawerToggle = new ActionBarDrawerToggle(
this,
mDrawerLayout,
R.drawable.ic_drawer,
R.string.drawer_open,
R.string.drawer_close
) {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
if (slideOffset == 0
&& getActionBar().getNavigationMode() == ActionBar.NAVIGATION_MODE_STANDARD) {
// drawer closed
getActionBar()
.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
invalidateOptionsMenu();
} else if (slideOffset != 0
&& getActionBar().getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS) {
// started opening
getActionBar()
.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
invalidateOptionsMenu();
}
super.onDrawerSlide(drawerView, slideOffset);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
- Use
onDrawerStateChanged(int newState)
callback
You need to listen to STATE_SETTLING
states - this state is reported whenever drawer starts moving (either opens or closes). So once you see this state - check whether drawer is opened now and act accordingly:
mDrawerToggle = new ActionBarDrawerToggle(
this,
mDrawerLayout,
R.drawable.ic_drawer,
R.string.drawer_open,
R.string.drawer_close
) {
@Override
public void onDrawerStateChanged(int newState) {
if (newState == DrawerLayout.STATE_SETTLING) {
if (!isDrawerOpen()) {
// starts opening
getActionBar()
.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
} else {
// closing drawer
getActionBar()
.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
}
invalidateOptionsMenu();
}
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
Solution 2
Currently accepted answer by Pavel Dudka is already deprecated.
Please use mDrawerLayout.addDrawerListener()
method instead to set a listener.
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
//Called when a drawer's position changes.
}
@Override
public void onDrawerOpened(View drawerView) {
//Called when a drawer has settled in a completely open state.
//The drawer is interactive at this point.
// If you have 2 drawers (left and right) you can distinguish
// them by using id of the drawerView. int id = drawerView.getId();
// id will be your layout's id: for example R.id.left_drawer
}
@Override
public void onDrawerClosed(View drawerView) {
// Called when a drawer has settled in a completely closed state.
}
@Override
public void onDrawerStateChanged(int newState) {
// Called when the drawer motion state changes. The new state will be one of STATE_IDLE, STATE_DRAGGING or STATE_SETTLING.
}
});
Works perfectly. Cheers!
Solution 3
try to override a method of DrawerLayout.DrawerListener
@Override
public void onDrawerStateChanged(int newState) {
if( newState == DrawerLayout.STATE_DRAGGING && isDrawerOpen() == false ) {
// this where Drawer start opening
}
}
Solution 4
Up-to-date solution:
As others have suggested, the current answer is outdated and it's advised to use mDrawerLayout.addDrawerListener()
. A working solution would then be:
mDrawerLayout.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
@Override
public void onDrawerStateChanged(int newState) {
if (newState == DrawerLayout.STATE_SETTLING && !mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
// Drawer started opening
}
}
});
Naturally, replace GravityCompat.START
with whatever identifies your drawer (layout ID or its gravity ~ location).
Also, if you want to detect when the drawer starts closing, you can simply do:
mDrawerLayout.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
@Override
public void onDrawerStateChanged(int newState) {
if (newState == DrawerLayout.STATE_SETTLING) {
if (!mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
// Drawer started opening
} else {
// Drawer started closing
}
}
}
});
Solution 5
For Kotlin
var toggle = object : ActionBarDrawerToggle(this,
drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {
override fun onDrawerOpened(drawerView: View) {
super.onDrawerOpened(drawerView)
}
}
drawer_layout.addDrawerListener(toggle)
toggle.syncState()
Oleksiy
Updated on July 08, 2022Comments
-
Oleksiy almost 2 years
So I have tabs that I want to hide when the Navigation Drawer starts opening. The code I have hides them when it finished opening, but it's not what I want.
mDrawerToggle = new ActionBarDrawerToggle( this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close ) { @Override public void onDrawerClosed(View view) { invalidateOptionsMenu(); setActionBarMode(ActionBar.NAVIGATION_MODE_TABS); } @Override public void onDrawerOpened(View drawerView) { invalidateOptionsMenu(); setActionBarMode(ActionBar.NAVIGATION_MODE_STANDARD); } }; mDrawerLayout.setDrawerListener(mDrawerToggle);
Here's what I tried:
- Setting an
onClickListener
tomDrawerLayout
.onClick
never gets called - Setting an
onTouchListener
tomDrawerLayout
.onTouch
never gets called - Researched
ActionBarDrawerToggle
andDrawerLayout
classes. Could not find anything likeonDrawerStartedOpening
.
- Setting an
-
Oleksiy about 10 yearsThe first approach worked for me, however there was one issue. When I tried to slide the drawer not all the way and release it to go to its original position, the tabs didn't restore. It turned out that the call to
invalidateOptionsMenu();
has to be beforesetNavigationMode
. Everything else worked fine. Thanks! -
Parth Sharma almost 9 yearsHow i can hide something(Like: FAB button) using onDrawerStateChanged in my MainActivity where i have implement my navigation drawer.. ?
-
Micro about 8 yearsGetting a lot deprecated code notifications and "cannot resolve isDrawerOpen()" errors when using
onDrawerSlide
... Is there an updated answer? -
Edijae Crusar almost 8 years@ first approach is super awesome
-
Mahendran Sakkarai about 7 years
setDrawerListener
is deprecated. Changed toaddDrawerListener
. developer.android.com/reference/android/support/v4/widget/… -
c0dehunter over 6 years
isDrawerOpen()
is not defined. Where is it from? -
RamithDR about 6 yearsMost up to date answer! Thanks!
-
Allan Veloso over 5 years@PrimožKralj Use DrawerLayout.isDrawerOpen(int drawerGravity)
-
ElliotM over 5 years
DrawerLayout.SimpmleDrawerListener
is also available and provides no-ops for stuff you don't need. -
Renetik over 2 yearsThis statement is wrong!!! "STATE_SETTLING states - this state is reported whenever drawer starts moving (either opens or closes)" Obviously it is what is written "Indicates that a drawer is in the process of settling to a final position" so you get it late not in the start so unusable for op question. You should remove this from your answer. I just wasted some time because I was testing that because I liked idea at first sight.
-
Pavel Dudka over 2 years@Renetik, well, I would say you should be careful when using a SO answer from 2014 :) I bet APIs have changed since then
-
Renetik over 2 years@PavelDudka well sure it changes all the time in some places but here I didn't expect it and answer should be then updated ... I wrote here my answer too after I found issues so maybe this is stack overflow logic that something accepted as answer is true answer forever should be somehow improved.