如何管理具有子片段的后退堆栈?

4
我遇到了关于嵌套/子Fragment的问题。我的使用情况是:我有一个作为父Fragment的Frag A,还有要显示在Frag A内的子Fragment,包括FragChild1、FragChild2和FragChild3。现在,当从FragChild3返回时,它应该像这样工作:

FragChild3-> FragChild2-> FragChild1-> FragA(ParentFrag)。

我用来添加子Fragment的代码如下所示-

for ChildFrag1-

Fragment mChildFragment1 = new ChildFragment1();
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        transaction.replace(R.id.container_view, mChildFragment1);
        transaction.addToBackStack("FragChild1");
        transaction.commit();
        
for ChildFrag2-

Fragment mChildFragment2 = new ChildFragment2();
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        transaction.replace(R.id.container_view, mChildFragment2);
        transaction.addToBackStack("FragChild2");
        transaction.commit();

我已经在StackOverflow上搜索了相关答案,但还没有找到任何适当的答案/方法来管理子片段的后退堆栈。


片段3是片段2的子级,而片段2是片段1的子级吗? - Jordan
我想要一个ViewPager的行为与子片段,但我正在使用getChildFragmentManager()。 - Bella
你需要在承载所有这些片段的活动中重写onBackPressed()事件,并且每次按下返回按钮时手动检查哪个片段位于堆栈的顶部。 - Jordan
为什么不让 ViewPager 处理这种行为呢? - Greggz
这个回答解决了你的问题吗?Android 4.2:嵌套片段的返回堆栈行为 - Daniil Pavlenko
显示剩余9条评论
4个回答

4

你的代码看起来很好。只需在包含父片段的活动中覆盖 onbackpressed 方法,并将给定的代码放入其中即可。

if (parentfragment.getChildFragmentManager().getBackStackEntryCount() > 1) {
    parentfragment.getChildFragmentManager().popBackStackImmediate();
} else {
    super.onBackPressed();
}

我们可以使用parentfragment.getChildFragmentManager().popBackStackImmediate()的结果作为if()的条件。 - Tuan Chau

1
现在,可以使用OnBackPressedDispatcher来实现此行为,而无需在Activity中覆盖onBackPressed

在您的父片段(包含您的片段容器的位置)中,在onAttach方法中添加此代码:

override fun onAttach(context: Context) {
    super.onAttach(context)
    val backCallback = object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            // Remove all fragments from the childFragmentManager,
            // but exclude the first added child fragment.
            // This child fragment will be deleted with its parent.
            if (childFragmentManager.backStackEntryCount > 1) {
                childFragmentManager.popBackStack()
                return
            }
            // Delete parent fragment
            parentFragmentManager.popBackStack()
        }
    }
    requireActivity().onBackPressedDispatcher.addCallback(this, backCallback)
}

然后在您的容器中添加类似以下的片段:

childFragmentManager.commit {
    replace(R.id.fragmentContainerRoot, fragment)
    addToBackStack(null)
}

0
将标签传递到replace方法中。TAG可以简单地作为片段名称(字符串)。将您的代码更改为以下内容:
transaction.replace(R.id.container_view, mChildFragment1, "FragChild1");
transaction.addToBackStack("FragChild1");
transaction.commit();

那样有什么帮助呢? - Bella
你试过使用add()而不是replace()吗?因为replace会清除所有内容并添加新的片段。如果你使用replace()和addToBackStack(),你需要重写onBackPressed()方法。 - Prashanth Verma
如果我添加而不是替换,则子片段会重叠。我将子片段放置在父容器的单个容器中。 - Bella
如何实现在按下返回键时弹出每个子片段覆盖的行为? - Bella
我建议将所有逻辑放在活动中,这意味着片段的打开应该在活动中进行,您不应该从片段A打开片段B,而是告诉活动应该打开片段B(使用接口)。现在重写活动的onbackpressed而不是片段的。 - Prashanth Verma

0

试试这个,

Fragment fragment= new ChildFragment1();
getChildFragmentManager().beginTransaction().replace(R.id.contentView, fragment).addToBackStack(fragment.getClass().getName()).commitAllowingStateLoss();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接