DrawerLayout的项目点击 – 何时是正确的时间来replace片段?

我正在开发一个使用导航抽屉模式(使用DrawerLayout)的应用程序。

每次点击一个抽屉的物品,将replace主容器中的碎片。

但是,我不确定什么时候是合适的时间做碎片交易? 当抽屉开始closures? 或closures后?

在google的documentaion示例中 ,您可以看到他们正在单击项目后执行交易,然后closures抽屉。
因此,抽屉看起来很不平滑,而且看起来很不好(这也发生在我的应用程序中)。

另一方面,在Gmail和Google Drive应用程序中,似乎他们在抽屉closures之后正在进行交易(是吗?)。
因此,抽屉不是非常滞后,非常平滑的,但至less需要1秒钟(抽屉被closures的时间)才能看到下一个碎片。

立即进行碎片交易似乎没有办法让抽屉顺利。

你怎么看?

提前致谢!

是的,不能同意更多,执行一个片段(与视图)交易结果布局通过,导致视图上的animationDrawerLayoutanimation,援引DrawerLayout 文档 :

DrawerLayout.DrawerListener可用于监视抽屉视图的状态和运动。 避免在animation中执行布局等昂贵的操作,因为这会导致口吃; 尝试在STATE_IDLE状态期间执行昂贵的操作。

所以请在抽屉closures后执行你的分片交易,或者有人补充支持库,以某种方式修复:)

另一个解决scheme是在closures抽屉后创buildHandler并发布延迟的Runnable ,如下所示: https : //stackoverflow.com/a/18483633/769501 。 这种方法的好处是,如果你等待DrawerListener#onDrawerClosed() ,你的碎片将被更换,但是当然任意延迟并不能100%保证抽屉animation能及时完成。

这就是说,我使用200毫秒的延迟,它奇妙地工作。

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

这就是我为了实现类似于Gmail应用的stream畅的交易animation所做的事情:

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(); ... @Override public 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; } } } 

希望能帮到你! 🙂

我知道这个问题是旧的,但我遇到了同样的问题,并认为我会发布我的解决scheme,因为我认为这是一个比添加硬编码延迟时间更好的实现。 我所做的是使用onDrawerClosed函数来validation抽屉在执行任务之前是否closures。

 //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 } 

然后在onDrawerClosed ,打开相应的活动。

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

如果你希望它顺利,没有任何延迟,打开抽屉,并在返回时closures它(在onRestart()方法)。

 @Override protected void onRestart() { // TODO Auto-generated method stub super.onRestart(); mDrawerLayout.closeDrawer(mDrawerList); } 

副作用是返回时的(快速)animation,但这可能是可以接受的。

只需将您的代码写入处理程序,并延迟200毫秒。

  new Handler().postDelayed(new Runnable() { @Override public void run() { openSelectionDrawerItem(position); } }, 200); 

而不是延迟您的项目点击,这可能会使您的应用程序感觉缓慢。 我只是推迟closuresmDrawerLayout。 我不会使用DrawerLayout.OnDrawerListener onClose(...) ,因为这些callback太慢,无法调用。

 new Handler().postDelayed(new Runnable() { @Override public void run() { mDrawerLayout.closeDrawer(GravityCompat.START); } }, 200);