我想扩展@rupps 所说的内容,因为我觉得关于 FragmentManager/Transaction 所做的部分不是从您所期望的地方进行的。
我假设您使用的是BottomNavigationView。
无论 Fragment 的(重要)生命周期如何,您都必须了解 Fragment 始终附加到一个 Activity(注意:这不是真的,但我们现在先不讨论无头 Fragment )。
您可以采取的方法是 Activity 布局如下所示:(在伪代码中)
<RelativeLayout width=match_parent height=match_parent>
<FrameLayout
id="@+id/your_fragment_container"
width=match_parent
height=match_parent
layout_above="@+id/navbar" />
<BottomNavigationView
id="@id/navbar"
width=match_parent
height=wrap_content
align_parent_bottom=true />
</RelativeLayout>
这样,BottomNavBar 将始终出现在布局的底部。
现在您必须处理将片段放在那里...假设您需要将Listener 附加到该栏,并且当您收到已选择新菜单项的回调时...您可以继续更改片段(你总是会在启动时得到一个事件,或者我想你可以在 onCreate 期间强制它)。
您将在 onNavigationItemSelected(MenuItem item) 方法中添加一个 switch/if 语句。
并调用addFragment(TAG);,具体取决于哪个case。
伪代码供你理解:
private void addFragment(final String tag) {
final Fragment existing = getSupportFragmentManager().findFragmentByTag(tag);
if (existing == null) {
final Fragment newInstance = getNewFragmentInstanceWithTag(tag);
getSupportFragmentManager()
.beginTransaction()
.replace(getFragmentContainerLayout(), newInstance, tag)
.commit();
}
}
您还需要提供:
private int getFragmentContainerLayout() {
return R.id.your_fragment_container;
}
还有……
public static final String TAB1_TAG = "TAB1_TAG";
public static final String TAB2_TAG = "TAB2_TAG";
public static final String TAB3_TAG = "TAB3_TAG";
protected Fragment getNewFragmentInstanceWithTag(String tag) {
switch (tag) {
case TAB1_TAG:
return Tab1Fragment.newInstance();
case TAB2_TAG:
return Tab2Fragment.newInstance();
case TAB3_TAG:
return Tab3Fragment.newInstance();
default:
return null;
}
}
那么,FragmentManager/Transaction 到底是什么青蛙?
将 Manager 视为一个单例对象(每个应用一个),它保留对您的 Fragment 的引用并可以为您检索它们(如果它们以前存在的话)。它处理事务(添加/删除/隐藏/显示等),因此您可以稍后回滚它们(例如,您在事务中添加一个片段,如果您还 addToBackStack() 那么您可以简单地告诉经理:弹出最后一个事务,有效地回滚。
这是一个怪物。它有超过 9000 年的错误,而且不是很直观;但是一旦你习惯了它,你就“使用它”。