【问题标题】:Fragment not replaced when using backstack使用 backstack 时片段未替换
【发布时间】:2014-08-15 19:14:19
【问题描述】:

我有一个使用抽屉式导航的应用程序。抽屉让您可以在 2 个片段之间导航: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。

将 F1 替换为 F3:

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 通过返回按钮(backstack)。
导航抽屉 F1 到 F2

最后一个片段 (F2) 不会替换 F1 ,而是出现在上方,就像我添加了它一样:

执行相同的导航但不使用后退按钮按预期工作。

为什么 backstack 搞乱了片段替换?

我的目标是在 F1 和 F3 之间提供后退导航,但不在导航抽屉访问的片段之间提供导航。

【问题讨论】:

    标签: android android-fragments navigation back-stack


    【解决方案1】:

    让我们了解每一步会发生什么:

    • F1 到 F3 按按钮。

    由于调用了addToBackStack,因此为此事务创建了一个回栈条目。在后面的堆栈条目中记录了 2 个操作:

    op1:删除 F1

    op2:加F3

    • 导航抽屉按 F3 到 F2。

    如果导航抽屉你没有使用addToBackStack,那么后面的堆栈完全不知道这个删除F3并添加F2的事务。

    • F2 到 F1 按返回按钮(backstack)。

    按下返回按钮时,最后记录的返回堆栈条目的操作将被反转。最后记录的条目是删除 F1 并添加 F3。预期的结果是:

    op1: 移除 F1 => 添加 F1

    op2: 添加 F3 => 删除 F3

    由于 F3 在之前的事务中已经被移除,所以没有操作。后堆栈完全不知道 F2,因此保持原样。在此事务结束时,F1 和 F2 都被添加到活动窗口中。由于 F1 的大小比 F2 大,所以看不到。

    • 导航抽屉按 F1 到 F2

    此事务只会将 F2 置于 F1 之上,因为两者都已添加到活动窗口中。

    解决方案:由于后退导航应该只发生在 F1 和 F3 之间,所以当用户使用导航抽屉导航到不同的 Fragment 时,只需清除后退堆栈即可。

    FragmentManager fm = getActivity().getFragmentManager();
    for(int i = 0; i < fm.getBackStackEntryCount(); i++) {    
        fm.popBackStack();
    }
    

    【讨论】:

      【解决方案2】:

      试试这个

      getFragmentManager().beginTransaction()
                      .replace(R.id.content_frame, new GameFragment())
                      .addToBackStack(null).commit();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-17
        • 1970-01-01
        • 2012-12-30
        • 2014-09-26
        • 1970-01-01
        • 2020-08-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多