37

我的场景:活动 1 由片段 A-> B-> C 组成。所有片段都使用以下代码添加:

        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.content, fragment, TAG);
        ft.addToBackStack(TAG);
        ft.commit();

现在,从片段C,我想直接返回片段A。因此,我ft.addToBackStack(TAG)在添加片段C时进行了评论。所以当我从CI按下返回按钮时,直接在屏幕上获取片段A。

但是,Fragment C 并没有被 A 取代。实际上,这两个 Fragment 都是可见的。我该如何解决这个问题?

4

3 回答 3

30

您需要做 2 件事 - 从 A->B 命名 FragmentTransaction,然后在包含活动中覆盖 onBackPressed() 以在 Fragment C 上调用FragmentManager#popBackStack (String name, int flags)。示例:

从 A->B 过渡

getSupportFragmentManager()
  .beginTransaction()
  .replace(R.id.container, new FragmentB(), "FragmentB")
  .addToBackStack("A_B_TAG")
  .commit();

从 B->C 的转换将使用以“FragmentC”作为其标记的类似事务。

然后在您包含的 Activity 中覆盖 onBackPressed():

@Override
public void onBackPressed() {
  if (getSupportFragmentManager().findFragmentByTag("FragmentC") != null) {
    // I'm viewing Fragment C
    getSupportFragmentManager().popBackStack("A_B_TAG",
      FragmentManager.POP_BACK_STACK_INCLUSIVE);
  } else {
    super.onBackPressed();
  }
}
于 2013-02-05T18:18:53.807 回答
20

理论

使用 中的addToBackStack(tag: String): FragmentTransaction方法FragmentTransaction来标记要返回的点。此方法FragmentTransaction仅返回链能力的实例。

然后popBackStackImmediate(tag: String, flag: int): void使用FragmentManager. 标签是您之前指定的。该标志要么是POP_BACK_STACK_INCLUSIVE包含标记的事务的常量,要么是0

例子

下面是一个带有以下布局的示例,该布局具有一个FrameLayout带有 idcontent_frame的片段被加载到的位置。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />

<FrameLayout
    android:id="@+id/content_frame"
    android:layout_below="@id/textView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

</RelativeLayout>

下面的代码在用 id 替换布局元素的内容时通过片段类名标记片段content_frame

public void loadFragment(final Fragment fragment) {
    
    // create a transaction for transition here
    final FragmentTransaction transaction = getSupportFragmentManager()
            .beginTransaction();
            
    // put the fragment in place
    transaction.replace(R.id.content_frame, fragment);

    // this is the part that will cause a fragment to be added to backstack,
    // this way we can return to it at any time using this tag
    transaction.addToBackStack(fragment.getClass().getName());

    transaction.commit();
}

为了完成这个例子,一个方法允许您在加载时使用标签返回到完全相同的片段。

public void backToFragment(final Fragment fragment) {

    // go back to something that was added to the backstack
    getSupportFragmentManager().popBackStackImmediate(
            fragment.getClass().getName(), 0);
    // use 0 or the below constant as flag parameter
    // FragmentManager.POP_BACK_STACK_INCLUSIVE);

}

当真正实现这一点时,您可能希望在片段参数上添加一个空检查;-)。

于 2013-09-27T15:51:02.703 回答
0

我就是这样做的。。

使用FragmentA.java和任何其他片段。

用它的类名替换你的片段作为标签:

private void showFragment(Fragment fragment){
        if(fragment != null){
            getSupportFragmentManager().beginTransaction().replace(R.id.container,fragment,fragment.getClass().getSimpleName()).commit();
        }
    }

现在在 onBackPressed() 中:

@Override
    public void onBackPressed()
    {
if(getSupportFragmentManager().findFragmentByTag("FragmentA") == null)
            showFragment(new FragmentA());
        else
            super.onBackPressed();
    }
于 2020-12-02T09:09:09.787 回答