我的问题如下:
我有一个应用程序有一个主要活动,其中有 是一个frameLayout容器(containerViewId),用于在菜单导航器选择时显示/膨胀不同的片段。
我实际上做的是在onCreate()活动上创建所有片段对象并将其添加到frameLayout:
伪代码:
//在主要活动中 的onCreate()
Fragment1 fragment_1 = new Fragment1();
Fragment2 fragment_2 = new Fragment2()
Fragment3 fragment_3 = new Fragment3()
fragmentTransaction.add(containerViewId, fragment_1, "frag_1");
fragmentTransaction.add(containerViewId, fragment_2, "frag_2");
fragmentTransaction.add(containerViewId, fragment_3, "frag_3");
// hide fragments 2&3, so only fragment_1 is showed
fragmentTransaction.hide(fragment_2);
fragmentTransaction.hide(fragment_3);
.commit()..
现在,当用户从导航视图中选择特定选项时,我就是这样 隐藏显示的当前片段,并显示如下所示的片段(例如从fragment_1切换到fragment_2):
fragmentTransaction.hide(fragment_1);
fragmentTransaction.show(fragment_2);
fragmentTransaction.commit();
一切都按预期工作(片段成功切换),但我有时观察到一段时间后(当我将我的应用从背景带到前面时),之前的片段突然显示/重叠在一起(即使我总是隐藏当前片段片段并显示下一个)
我错过了什么吗? 为什么突然显示我之前的观点?
谢谢: - )
答案 0 :(得分:1)
您需要替换而不是堆叠片段。如果您希望能够导航回上一个片段,请使用addToBackStack
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
fragmentmanager上有一些方法可以从backstack获取或弹出以前的片段:popBackStack(),getBackStackEntryAt(int index)等等。
<强>更新强>
方法popBackStack弹出backstack的顶部。靠背包含BackStackEntries。 Backstack条目仅包含片段的一些引用字段。您应该将片段作为变量保存在包含的类中,以便可以替换它们。请注意,您应始终实施适当的生命周期管理,因为在Android中,如果您在后台拥有数据,则无法确定数据是否仍在内存中。
以下是有关活动生命周期的一些信息,但对于片段,它们大致相同:
当您的活动在之前被销毁之后重新创建时,您 可以从系统通过的Bundle恢复已保存的状态 你的活动。 onCreate()和onRestoreInstanceState() 回调方法接收包含实例的相同Bundle 国家信息。
因为无论系统是否正在创建,都会调用onCreate()方法 您必须在活动的新实例或重新创建前一个实例 在尝试读取之前检查状态Bundle是否为null。 如果为null,则系统正在创建新的实例 活动,而不是恢复之前被破坏的活动。
有关片段生命周期的一些官方文档:https://developer.android.com/guide/components/fragments.html#Lifecycle
答案 1 :(得分:0)
保持简单。做这样的事情 -
Fragment1 fragment_1 = new Fragment1();
Fragment2 fragment_2 = new Fragment2();
Fragment3 fragment_3 = new Fragment3();
fragmentTransaction.replace(containerViewId, fragment_1, "frag_1"); //when you want show fragment 1
fragmentTransaction.commit();
//similarly just replace with fragment2 and fragment 3 when you want to show them respectively.The trick is to replace (which internally removes all previously added fragments before adding the current fragment, thus no overlapping issues)