I\'m developing an application which uses the navigation drawer pattern (With DrawerLayout).
Each click on a drawer\'s item, replaces the fragment in the main contai
Another solution is to create a Handler
and post a delayed Runnable
after you close the drawer, as shown here: https://stackoverflow.com/a/18483633/769501. The benefit with this approach is that your fragments will be replaced much sooner than they would be if you waited for DrawerListener#onDrawerClosed()
, but of course the arbitrary delay doesn't 100% guarantee the drawer animation will be finished in time.
That said, I use a 200ms delay and it works wonderfully.
private class DrawerItemClickListener implements OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
drawerLayout.closeDrawer(drawerList);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
switchFragments(position); // your fragment transactions go here
}
}, 200);
}
}
If you want it smooth and without any delay, leave the drawer open and close it afterwards when returning (in the onRestart() method).
@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
mDrawerLayout.closeDrawer(mDrawerList);
}
The side effect is an (speedy) animation when returning, but this might be acceptable.
I know this question is old but I ran into the same problem and figured I would post my solution as I think it is a better implementation than adding a hardcoded delay time. What I did was use the onDrawerClosed
function to verify that the drawer IS closed before doing my task.
//on button click...
private void displayView(int position) {
switch (position) {
//if item 1 is selected, update a global variable `"int itemPosition"` to be 1
case 1:
itemPosition = 1;
//();
break;
default:
break;
}
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
mDrawerLayout.closeDrawer(mDrawerList); //close drawer
}
and then in onDrawerClosed
, open the corresponding activity.
public void onDrawerClosed(View view) {
getSupportActionBar().setTitle(mTitle);
// calling onPrepareOptionsMenu() to show action bar icons
supportInvalidateOptionsMenu();
if (itemPosition == 1) {
Intent intent = new Intent(BaseActivity.this, SecondActivity.class);
startActivity(intent);
}
}
Instead of delaying your item clicks which may make your app feel slow. I would just delay the closing of the mDrawerLayout. I would not use the DrawerLayout.OnDrawerListener onClose(...)
either because those callbacks are so slow to be called.
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mDrawerLayout.closeDrawer(GravityCompat.START);
}
}, 200);
Yup, couldn't agree more, performing a fragment (with view) transaction results in a layout pass which causes janky animations on views being animated, citing DrawerLayout
docs:
DrawerLayout.DrawerListener can be used to monitor the state and motion of drawer views. Avoid performing expensive operations such as layout during animation as it can cause stuttering; try to perform expensive operations during the STATE_IDLE state.
So please perform your fragment transactions after the drawer is closed or somebody patches the support library to somehow fix that :)
Just write your code in a handler and put 200 ms delay.
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
openSelectionDrawerItem(position);
}
}, 200);