10

我对 Android 开发相当陌生,现在遇到了奇怪的行为。

  • 我有一个空的 FrameLayout 作为片段的容器。
  • 如果用户第一次按下按钮,则生成新的 Fragment 并放入容器中。
  • 如果用户稍后按下按钮并且容器内有现有片段,则将现有片段替换为新生成的片段。
  • 如果用户按下后退按钮,则弹出容器内的片段。

这是我的代码

public void showFragment(View v) {
    FragmentA f = new FragmentA();

    FragmentManager fm = getSupportFragmentManager();
    String tag = f.getFragmentTag(); // instance method of a to get a tag

    FragmentTransaction ft = fm.beginTransaction();
    ft.setCustomAnimations(R.anim.slide_in_top, 0, 0, R.anim.slide_out_top);            
    ft.replace(R.id.container, f, tag);
    ft.addToBackStack(tag);
    ft.commit();
}

@Override
public void onBackPressed() {
    FragmentManager fm = getSupportFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        fm.popBackStack();
    } else {
        super.onBackPressed();
    }
}

当用户第一次按下按钮时,它的行为就像我预期的那样,将新片段添加到容器中。但是,当容器仍然包含一个片段时,用户第二次按下按钮,而不是替换,它在现有片段之上添加新片段。因此,容器内有 2 个碎片,2 次后按以移除所有碎片。

我发现如果我删除线

ft.addToBackStack();

并像下面那样重做 onBackPress() 方法,它再次像我预期的那样工作(一次容器中的 1 个片段)

基本上,手动删除片段而不是 popFromBackStack 方法

private FragmentA currentFragment = null; // to hold the reference to exising fragment, if any.

@Override
public void onBackPressed() {
    if (currentFragment != null) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.setCustomAnimations(0, R.anim.slide_out_top);
        ft.remove(currentFragment);
        ft.commit();

        currentFragment = null;
    } else {
        super.onBackPressed();
    }
}

所以,我的问题是

  • replace 和 addToBackStack 不能一起工作?
  • 或者,我做错了什么?

感谢所有意见和建议。

4

2 回答 2

13

addToBackstack创建片段状态的快照。这意味着当您按下后退按钮时,您实际上是恢复到上次addToBackstack调用的状态。

在您的情况下,您添加了一个片段。后退按钮将删除这个添加的片段。当您调用 replace 并再次添加到 backstack 时,您现在在 backstack 上有两种状态(1. 当您添加了第一个片段时,2. 当您没有添加片段时)。如果你用后退按钮移除当前片段,就不要使用 addToBackstack。仅当您想在视图中保留片段的状态时才使用 addToBackstack。

于 2013-12-19T04:43:27.660 回答
-2

对于那些仍在寻找解决方案的人。

在主Activity类(托管片段)中,只需覆盖onBackPressed().

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0 ){
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}

fragment中没有onBackPressed()方法,该方法仅适用于activity. 因此,当我们按下返回键时,会显示 的默认行为activity,即

你要么去以前的活动(如果有的话)要么应用程序将退出。

现在我们需要重写这个方法来告诉activity我们当我们按下返回键时,如果返回堆栈中有任何片段,则将它们弹出(这是addToBackStack()出现图片的时候)。否则遵循默认行为。

在这里找到更多细节

于 2015-11-17T14:15:23.650 回答