我有一个使用导航抽屉的应用程序。抽屉可让您在两个片段之间导航:F1和F2:
活动布局:
<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"
android:background="@color/background"/>
<!-- The navigation drawer -->
<ListView android:id="@+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:dividerHeight="0dp"
android:background="#f5f5f5"/>
</android.support.v4.widget.DrawerLayout>
在Activity中替换片段的代码:
private void selectItem(int position) {
Fragment fragment;
fragment = getFragmentToDisplay(position);
if(fragment != null)
{
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment,"fragment_"+position)
.commit();
}
}
在F1上我有一个按钮来调用另一个片段(F3)。当F3替换F1时,我可以使用addToBackStack()
按返回返回F1。
用F3替换F1:
getFragmentManager().beginTransaction()
.replace(R.id.content_frame, new GameFragment())
.addToBackStack("Games").commit();
从F1到F2,F2到F1完美运作 从F1到F3,F3到F1(使用后退按钮)也可以。
然而,如果我正在做这个序列:
按钮按F1到F3
导航抽屉F3到F2。
通过后退按钮(后退)按F2到F1
导航抽屉F1到F2
最后一个片段(F2)不会取代F1,而是会显示在上面,就像我添加了它一样:
执行相同的导航但不使用后退按钮按预期工作。
为什么后台堆坏了碎片替换?
我的目标是在F1和F3之间提供后退导航,但不在导航抽屉访问的片段之间。
答案 0 :(得分:3)
让我们了解每一步发生的事情:
自调用addToBackStack
以来,为此事务创建了一个后栈条目。在后栈表项中记录2个操作:
op1:删除F1
op2:添加F3
如果导航抽屉没有使用addToBackStack
,那么后面堆栈完全不知道此事务中删除了F3并添加了F2。
按下后退按钮,最后记录的后退堆栈条目的操作将被反转。最后记录的条目是删除F1&amp;添加F3。预期结果将是:
op1:删除F1 =&gt;添加F1
op2:添加F3 =&gt;删除F3
由于F3在之前的交易中已被删除,因此没有操作。后栈完全没有意识到F2,因此保持不变。到此交易结束时,F1和F2都会添加到活动窗口中。由于F1尺寸大于F2,因此未见。
此交易只会将F2置于F1之上,因为两者都已添加到活动窗口中。
解决方案:由于后退导航只能在F1&amp; F3,当用户使用导航抽屉导航到不同的片段时,只需清除后面的堆栈。
FragmentManager fm = getActivity().getFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); i++) {
fm.popBackStack();
}
答案 1 :(得分:0)
试试这个
getFragmentManager().beginTransaction()
.replace(R.id.content_frame, new GameFragment())
.addToBackStack(null).commit();