当前位置: 首页 > 知识库问答 >
问题:

如何在后栈中只保留第一个添加的片段(片段重叠)?

邰棋
2023-03-14

场景我试图实现的目标:

  1. 使用两个框架容器加载活动(用于项目列表和详细信息)
  2. 在应用程序启动时,在listFrame中添加listFragment,在detailsFrame容器中添加一些初始infoFragment
  3. 在列表项中导航,而不将每个细节事务添加到后堆栈中(只希望在堆栈中保留infoFragment)
  4. 一旦用户点击后退按钮(向后导航),他就会返回到初始信息片段,即在启动时添加的信息片段
  5. 如果顺序反向导航暂停,则应用程序退出

我的代码

        protected override void OnCreate(Bundle savedInstanceState)
        {
...
            var listFrag = new ListFragment();
            var infoFrag = new InfoFragment();
            var trans = FragmentManager.BeginTransaction();
            trans.Add(Resource.Id.listFrame, listFrag);
            trans.Add(Resource.Id.detailsFrame, infoFrag);
            trans.Commit();
...
        }

        public void OnItemSelected(int id)
        {
            var detailsFrag = DetailFragment.NewInstance(id);
            var trans = FragmentManager.BeginTransaction();
            trans.Replace(Resource.Id.detailsFrame, detailsFrag);
            if (FragmentManager.BackStackEntryCount == 0)
                {
                    trans.AddToBackStack(null);
                }
            trans.Commit();
        }

我的问题:

点击后退按钮后,infoFrag与之前的detailFrag重叠!为什么?

共有3个答案

韩禄
2023-03-14
匿名用户

问题是您支持的事务有两个步骤:

  • 删除infoFrag
  • 添加细节frag(这是添加的第一个1细节容器

(我们知道,因为文档<代码>基本上与调用remove(Fragment)相同,当前添加的所有片段都是使用相同的containerViewId添加的,然后使用此处给出的相同参数添加(int、Fragment、String)

因此,每当系统还原一个事务时,它正好还原这两个步骤,并且它对添加到其中的最后一个细节框架(detailFrag)只字未提,因此它不会对它做任何事情。

我可以考虑两种可能的解决方法:

>

  • 保留对最后使用的详细信息的活动引用Frag并使用BackStackChange侦听器,以便每当值从1更改为0时(您必须跟踪以前的值),您还可以删除剩余的片段

    每次单击侦听器时,您都必须立即弹出Backstack()(以删除以前的事务)并在所有事务上添加Backstack()。在此解决方法中,您还可以使用一些setCustomAnimation魔术来确保它在屏幕上看起来很好(例如,使用0到0的alpha动画持续时间1,以避免以前的片段再次出现和消失。

    附言。我同意片段管理器/事务应该更聪明一点,它处理.替换()操作的回栈方式,但这就是它的工作方式。

    编辑:

    正在发生的事情是这样的(我在细节中添加数字以使其更加清晰)。请记住。替换()=.删除().添加()

    Transaction.remove(info).add(detail1).addToBackStack(null) // 1st time
    Transaction.remove(detail1).add(detail2) // 2nd time
    Transaction.remove(detail2).add(detail3) // 3rd time
    Transaction.remove(detail3).add(detail4) // 4th time
    

    现在我们有了布局的细节4:

    < Press back button >
         System pops the back stack and find the following back entry to be reversed
             remove(info).add(detail1);
         so the system makes that transaction backward.
         tries to remove detail1 (is not there, so it ignores)
         re-add(info) // OVERLAP !!!
    

    所以问题是系统没有意识到有一个细节4,并且事务是。替换(),它应该替换那里的任何内容。

  • 杨高翰
    2023-03-14

    Budius的解释很好。我阅读了他的建议,并实现了类似的导航,我想与其他人分享。

    而不是像这样替换片段:

    Transaction.remove(detail1).add(detail2)
    Transaction.remove(detail2).add(detail3)
    Transaction.remove(detail3).add(detail4)
    

    我在活动布局文件中添加了一个片段容器布局。它可以是LinearLayoutRelativeLayotFrameLayout等。所以在创建的活动中,我有这个:

    transaction.replace(R.id.HomeInputFragment, mainHomeFragment).commit();
    

    mainHomeFragment是我想在按下后退按钮时返回的片段,如infoFrag。然后,在每次下一笔交易之前,我提出:

    fragmentManager.popBackStackImmediate();
    transaction.replace(R.id.HomeInputFragment, frag2).addToBackStack(null).commit();
    

    fragmentManager.popBackStackImmediate();
    transaction.replace(R.id.HomeInputFragment, frag3).addToBackStack(null).commit();
    

    这样,您就不必跟踪当前显示的片段。

    邵毅
    2023-03-14

    您可以这样做:

    if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
       getSupportFragmentManager().popBackStack(getSupportFragmentManager().getBackStackEntryAt(0).getId(), getSupportFragmentManager().POP_BACK_STACK_INCLUSIVE);
    } else {
       super.onBackPressed();}
    

    在你们的活动中,所以你们要保留第一个片段。

    在第一个片段中,不应该有addToBackStack。但是,在其他方面,是的。

     类似资料:
    • 问题内容: 我有活动: 在此容器内,取决于所按下的按钮是FragmentA还是FragmentB。这些片段是嵌套子片段的 容器 。即,每个片段中都包含自己的导航堆栈。 在活动的onCreate中,我将实例化这两个片段: 然后,我继续互相替换: 到目前为止,一切都很好。但 问题: 每次我用fragmentB替换fragmentA时(反之亦然) -getChildFragmentManager() 破

    • 我正在使用UI导航图。我有片段和。我的应用程序在片段上启动,以显示一些信息。然后,用户可以按下后退键,以结束。然后,用户通常从中选择一些内容,并以结束。 通常,我可以从堆栈中弹出并显示。但是,当应用程序刚刚启动时,后面的堆栈中没有。我想我可以手动将添加到backstack,但我想知道导航UI图是否允许我这样做。 我无法更改应用程序片段的顺序。这意味着我仍然需要首先显示。

    • 我使用了和。 但它一次加载两个页面。 有什么方法可以在viewpager中只加载一个页面吗?

    • 我有一个事件序列,通过它,我已经将三个片段一个接一个地添加到背景堆栈中。这些片段,每一个都覆盖了活动的全屏。 我已经存储了从Frag1的提交返回。 现在在Frag3中,基于特定的单击,我想直接回到Frag1并丢弃/弹出之间的所有Fragments。 因此,单击此按钮时,我会向活动发送一条消息,该消息执行以下操作: 但我只是得到一个空白屏幕,所以我假设没有加载碎片。 我甚至试过:在commit-

    • 我想从片段到活动使用返回按钮使用工具栏返回图标。 碎片是我的抽屉菜单项 我该怎么做?