19

Back Stack 是否支持与 Android 中的嵌套 Fragment 交互?

如果是这样,我做错了什么?在我的实现中,后退按钮完全忽略了我将此事务添加到后退堆栈的事实。我希望这不是因为嵌套片段的问题,而只是我做错了一些事情。

以下代码位于我的一个片段中,用于将新片段与当前显示的任何嵌套片段交换:

     MyFragment fragment = new MyFragment();
     FragmentTransaction ft = getChildFragmentManager().beginTransaction();
     ft.setCustomAnimations(R.animator.slide_in_from_right, R.animator.slide_out_left, R.animator.slide_in_from_left, R.animator.slide_out_right);
     ft.addToBackStack(null);
     ft.replace(R.id.myFragmentHolder, fragment);
     ft.commit();
4

4 回答 4

30

我有同样的问题,我想嵌套片段,并为每个嵌套片段保留一个后堆栈。

但是......似乎这种情况不是由 v4 支持库处理的。在库中的 FragmentActivity 代码中,我可以找到:

public void onBackPressed() {
    if (!mFragments.popBackStackImmediate()) {
        finish();
    }
}

mFragments 代表活动的 FragmentManager,但似乎该管理器并未将流行“传播”给子管理器。一种解决方法是在子管理器上手动调用 popBackStackImmediate(),就像从 FragmentActivity 继承的活动中这样:

private Fragment myFragmentContainer;

    @Override
    public void onBackPressed() {
            if (!myFragmentContainer.getChildFragmentManager().popBackStackImmediate()) {
                finish(); //or call the popBackStack on the container if necessary
            }
    }

可能有更好的方法,更自动化的方法,但根据我的需要,没关系。

于 2012-12-06T11:44:56.267 回答
4

在我当前的项目中,我们有多个“嵌套层”,所以我想出了以下解决方法,只为顶级片段管理器自动弹出回栈:

@Override
public void onBackPressed() {
    SparseArray<FragmentManager> managers = new SparseArray<>();
    traverseManagers(getSupportFragmentManager(), managers, 0);
    if (managers.size() > 0) {
        managers.valueAt(managers.size() - 1).popBackStackImmediate();
    } else {
        super.onBackPressed();
    }
}

private void traverseManagers(FragmentManager manager, SparseArray<FragmentManager> managers, int intent) {
    if (manager.getBackStackEntryCount() > 0) {
        managers.put(intent, manager);
    }
    if (manager.getFragments() == null) {
        return;
    }
    for (Fragment fragment : manager.getFragments()) {
        if (fragment != null) traverseManagers(fragment.getChildFragmentManager(), managers, intent + 1);
    }
}
于 2015-08-04T09:37:45.443 回答
4

API 26开始,有一个setPrimaryNavigationFragment方法FragmentTransaction可用于

将此 FragmentManager 中的当前活动片段设置为主导航片段。

这意味着

如果没有提供要弹出的 ID 或事务名称,将首先调用主导航片段的子 FragmentManager 来处理委托的导航操作,例如 FragmentManager.popBackStack()。片段系统之外的导航操作可以选择将这些操作委托给由 FragmentManager.getPrimaryNavigationFragment() 返回的主导航片段。

正如@la_urre 在接受的答案中所提到的,正如您在FragmentActivity's 的源代码中所看到的那样,FragmentActivity'sonBackPressed会调用它FragmentManager的 's popBackStackImmediate(),这反过来会检查是否存在mPrimaryNav(我假设的主要导航)片段,获取它的子片段管理器并弹出它的backstack。

于 2018-07-20T16:19:28.427 回答
-3
@Override
public void onBackPressed() {
    FragmentManager fm = getSupportFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        fm.popBackStack();
        return;
    }
    finish();
}
于 2014-07-15T16:15:14.423 回答