DrawerLayout's item click - When is the right time to replace fragment? DrawerLayout's item click - When is the right time to replace fragment? android android

DrawerLayout's item click - When is the right time to replace fragment?


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 :)


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);    }}


This is what I do to achieve an smooth transaction animation similar to Gmail app:

activity_drawer.xml

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/drawer_layout"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <!-- The main content view -->    <FrameLayout        android:id="@+id/content_frame"        android:layout_width="match_parent"        android:layout_height="match_parent" />    <!-- The navigation drawer -->    <ListView     android:id="@+id/left_drawer"        android:layout_width="280dp"        android:layout_height="match_parent"        android:layout_gravity="left"        android:choiceMode="singleChoice" /></android.support.v4.widget.DrawerLayout>

DrawerActivity.java

private Fragment mContentFragment;private Fragment mNextContentFragment;private boolean mChangeContentFragment = false;private Handler mHandler = new Handler();...@Overridepublic void onCreate(Bundle savedInstanceState) {    ...    mDrawerLayout.setDrawerListener(new DrawerListener());    mDrawerList.setOnItemClickListener(new DrawerItemClickListener());    ...}....private class DrawerItemClickListener implements ListView.OnItemClickListener {    @Override    public void onItemClick(AdapterView parent, View view, int position, long id) {        getSupportFragmentManager().beginTransaction().remove(mContentFragment).commit();        switch (position) {            case 0:                mNextContentFragment = new Fragment1();                break;            case 1:                mNextContentFragment = new Fragment2();                break;            case 2:                mNextContentFragment = new Fragment3();                break;        }        mChangeContentFragment = true;        mDrawerList.setItemChecked(position, true);        mHandler.postDelayed(new Runnable() {            @Override            public void run() {                mDrawerLayout.closeDrawer(mDrawerList);            }                   }, 150);    }}private class DrawerListener implements android.support.v4.widget.DrawerLayout.DrawerListener {    @Override    public void onDrawerClosed(View view) {        if (mChangeContentFragment) {             getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).replace(R.id.content_frame, mNextContentFragment).commit();             mContentFragment = mNextContentFragment;                        mNextContentFragment = null;             mChangeContentFragment = false;         }     } }

Hope that helps you! :-)