Android 抽屉布局';s项目单击-何时是替换片段的正确时间?
我正在开发一个使用导航抽屉模式(带抽屉布局)的应用程序 每次单击抽屉中的项目,都会替换主容器中的片段 但是,我不确定何时是执行片段事务的正确时间? 抽屉什么时候开始关上?还是在它关闭之后 在谷歌的网站中,你可以看到他们正在做交易 在项目之后单击,然后关闭抽屉。Android 抽屉布局';s项目单击-何时是替换片段的正确时间?,android,android-fragments,navigation-drawer,fragmenttransaction,drawerlayout,Android,Android Fragments,Navigation Drawer,Fragmenttransaction,Drawerlayout,我正在开发一个使用导航抽屉模式(带抽屉布局)的应用程序 每次单击抽屉中的项目,都会替换主容器中的片段 但是,我不确定何时是执行片段事务的正确时间? 抽屉什么时候开始关上?还是在它关闭之后 在谷歌的网站中,你可以看到他们正在做交易 在项目之后单击,然后关闭抽屉。 结果,抽屉看起来很迟钝,不光滑,而且看起来很糟糕(这种情况也发生在我的应用程序中) 另一方面,在和应用程序中,似乎他们在抽屉关闭后进行交易(我说的对吗?)。 因此,抽屉不是拖拉的,也不是很平滑,但至少需要1秒钟(抽屉关闭所需的时间)才能看
结果,抽屉看起来很迟钝,不光滑,而且看起来很糟糕(这种情况也发生在我的应用程序中) 另一方面,在和应用程序中,似乎他们在抽屉关闭后进行交易(我说的对吗?)。
因此,抽屉不是拖拉的,也不是很平滑,但至少需要1秒钟(抽屉关闭所需的时间)才能看到下一个片段 看起来,在立即进行碎片交易时,出票人是不可能平顺的 你觉得怎么样
提前谢谢 是的,非常同意,执行片段(带视图)事务会导致布局过程,从而导致视图上的janky动画被动画化,引用
DrawerLayout
:
DroperLayout.DroperListener可用于监视抽屉视图的状态和运动。避免在动画期间执行昂贵的操作,如布局,因为这可能会导致口吃;尝试在空闲状态下执行昂贵的操作
因此,请在抽屉关闭或有人修补支持库后执行碎片事务,以某种方式解决此问题:)这是我为实现类似于Gmail应用程序的平滑事务动画所做的: 活动\u 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>
希望对你有帮助!:-) 另一个解决方案是在关闭抽屉后创建一个
处理程序
,并发布一个延迟的Runnable
,如下所示:。这种方法的好处是,与等待DrawerListener\#onDrawerClosed()
相比,您的片段将被替换得更快,但当然,任意延迟并不能100%保证抽屉动画能够及时完成
这就是说,我使用了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);
}
}
私有类DrawerItemClickListener实现了OnItemClickListener{
@凌驾
public void onItemClick(AdapterView父对象、视图、最终整型位置、长id){
抽屉布局。封闭抽屉(抽屉列表);
new Handler().postDelayed(new Runnable()){
@凌驾
公开募捐{
switchFragments(position);//您的片段事务转到这里
}
}, 200);
}
}
我知道这个问题很老,但我遇到了同样的问题,我想我会发布我的解决方案,因为我认为它比添加硬编码延迟时间更好。我所做的是在执行任务之前,使用onDrawerClosed
函数验证抽屉是否已关闭
//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
}
然后在绘图关闭中打开相应的活动
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);
}
}
如果您希望它平滑且没有任何延迟,请让抽屉保持打开状态,然后在返回时将其关闭(在onRestart()方法中)
返回时的副作用是(快速)动画,但这可能是可以接受的 只需在处理程序中编写代码并延迟200毫秒即可
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
openSelectionDrawerItem(position);
}
}, 200);
而不是延迟您的项目点击,这可能会使您的应用程序感觉缓慢。我会推迟mDrawerLayout的关闭。我也不会使用
DrawerLayout.OnDrawerListener onClose(…)
,因为调用这些回调非常慢
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mDrawerLayout.closeDrawer(GravityCompat.START);
}
}, 200);
我同意!当我让我的应用程序从抽屉的
onItemClick()
中启动新活动时,我会看到“快速关闭抽屉”动画。这可能是因为很多活动都发生在UI线程上。因此,现在我必须从DrawerLayout.DrawerListener
内部启动一个新活动。。。正如您所提到的,这会降低用户体验。是否可以更改抽屉关闭动画的速度?速度似乎是一个重要的属性来暴露。。。但我在文档中找不到它!)@SomeoneSomewhere你可以更改动画长度,但这绝对不是一个优雅的解决方案:@SomeoneSomewhere我确实不喜欢急促的关闭动画,但我不喜欢让用户等待更长的时间。你可以看看这个解决方案:我喜欢这个解决方案,但我真的不知道如何让后堆栈行为正常工作。我可以在replace事务中添加“addToBackStack”,但由于之前的内容已被删除,因此这并没有达到预期效果。我试图隐藏而不是删除,但这也不起作用。@pbergqvist要获得后堆栈行为,您可以做的是:1。在删除“旧内容片段”之前,请使用另一个变量保存它。2.重写活动中的onBackPressed方法,并将其中的内容片段替换为“旧内容片段”。@pbergqvist更好的方法。如果将“remove fragment”事务、mChangeContentFragment=true和处理程序post都放在一个名为setContentFragment(fragment fragment)的方法中,则可以在onBackPressed中使用此方法,以避免重写同一代码两次。这对你有用吗?我想那会有用的,但只需要退一步。否则,我会让我自己维护一个堆栈。后堆栈不需要更改-谷歌的应用程序切换片段都不需要通过“后退”按钮。这很让人困惑。是不是只有支持库遇到了这个问题?如何等到状态变为状态_IDLE?这种方法会产生另一个描述的问题,在提交过程中崩溃,然后按下任务菜单you sir,你是个救命恩人:D在关闭抽屉和开始一项新活动之间还有一段时间。从什么地方回来?易居
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
openSelectionDrawerItem(position);
}
}, 200);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mDrawerLayout.closeDrawer(GravityCompat.START);
}
}, 200);