场景我试图实现的目标:
我的代码:
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重叠!为什么?
问题是您支持
的事务有两个步骤:
(我们知道,因为文档<代码>基本上与调用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,并且事务是。替换(),它应该替换那里的任何内容。
Budius的解释很好。我阅读了他的建议,并实现了类似的导航,我想与其他人分享。
而不是像这样替换片段:
Transaction.remove(detail1).add(detail2)
Transaction.remove(detail2).add(detail3)
Transaction.remove(detail3).add(detail4)
我在活动布局文件中添加了一个片段容器布局。它可以是LinearLayout
、RelativeLayot
或FrameLayout
等。所以在创建的活动中,我有这个:
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();
这样,您就不必跟踪当前显示的片段。
您可以这样做:
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-
我想从片段到活动使用返回按钮使用工具栏返回图标。 碎片是我的抽屉菜单项 我该怎么做?