// Create new fragment and transaction FragmentManagerfragmentManager= ... FragmentTransactiontransaction= fragmentManager.beginTransaction(); transaction.setReorderingAllowed(true);
// Replace whatever is in the fragment_container view with this fragment transaction.replace(R.id.fragment_container, ExampleFragment.class, null);
Fragment 也能够托管一个或多个子 fragment。在 fragment 内,
您可以通过 getChildFragmentManager() 获取对管理 fragment 子级的 FragmentManager 的引用。
如果您需要访问其宿主 FragmentManager,可以使用 getParentFragmentManager()
托管 Fragment
fragment、其宿主以及与每个 fragment 关联的 FragmentManager 实例之间的关系如下图所示
两个界面布局示例,显示了 fragment 与其宿主 activity 之间的关系。每个示例中都有一个 activity 宿主。
这两个示例中的宿主 activity 都以 BottomNavigationView 的形式向用户显示顶级导航,
该视图负责以应用中的不同屏幕换出宿主 fragment,其中每个屏幕都实现为单独的 fragment
示例 1 中的宿主 fragment 托管两个子 fragment,这些子 fragment 构成拆分视图屏幕。
示例 2 中的宿主 fragment 托管一个子 fragment,该子 fragment 构成滑动视图的显示 fragment。
基于此设置,您可以将每个宿主视为具有与其关联的 FragmentManager,用于管理其子 fragment。
下图说明了这一点,并显示了 supportFragmentManager、parentFragmentManager 和 childFragmentManager 之间的属性映射
每个宿主都有与其关联的 FragmentManager,用于管理其子 fragment。
需要引用的相应 FragmentManager 属性取决于调用点在 fragment 层次结构中的位置,
以及您尝试访问的 fragment 管理器。对 FragmentManager 进行引用后,您就可以使用它来操纵向用户显示的 fragment。
子 fragment 的管理
一般来说,应用应由应用项目中的一个或少数几个 activity 组成,其中每个 activity 表示一组相关的屏幕。
activity 可能会提供一个点来放置顶级导航,并提供一个位置来限定 ViewModels 以及 fragment 之间的其他视图状态的范围。
应用中的每个目的地应由一个 fragment 来表示。
如果您想要一次显示多个 fragment(如在拆分视图中或信息中心内),应使用子 fragment,
它们由目的地 fragment 及其子 fragment 管理器进行管理。子 fragment 的其他用例可能包括:
1.屏幕滑动,其中父 fragment 中的 ViewPager2 管理一系列子 fragment 视图。
2.一组相关屏幕中的子导航。
3.Jetpack Navigation 将子 fragment 用作各个目的地。一个 activity 托管一个父 NavHostFragment,
并在用户浏览应用时以不同的子目的地 fragment 填充它的空间。
FragmentManagerfragmentManager= getSupportFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.fragment_container, ExampleFragment.class, null) .setReorderingAllowed(true) .addToBackStack("name") // name can be null .commit();
在本例中,ExampleFragment 会替换当前在布局容器中的 fragment(如有),
该布局容器由 R.id.fragment_container ID 进行标识。
将 fragment 的类提供给 replace() 方法可让 FragmentManager 使用其 FragmentFactory 处理实例化
setReorderingAllowed(true) 可优化事务中涉及的 fragment 的状态变化,
以使动画和过渡正常运行。如需详细了解如何使用动画和过渡进行导航
addToBackStack() 会将事务提交到返回堆栈。用户稍后可以通过按“返回”按钮反转事务,并恢复上一个 fragment。
如果您在一个事务中添加或移除了多个 fragment,弹出返回堆栈时,所有这些操作都会撤消。
在 addToBackStack() 调用中提供的可选名称使您能够使用 popBackStack() 弹回到该特定事务
如果您在执行移除 fragment 的事务时未调用 addToBackStack(),则提交事务时会销毁已移除的 fragment,
用户无法返回到该 fragment。如果您在移除某个 fragment 时调用了 addToBackStack(),
则该 fragment 只会 STOPPED,稍后当用户返回时它会 RESUMED。请注意,在这种情况下,其视图会被销毁
查找现有 fragment
可以通过 findFragmentById() 或者 findFragmentByTag() 获取对布局容器中当前 fragment 的引用
findFragmentById()
可使用 findFragmentById() 按给定的 ID 查找 fragment;
在 FragmentTransaction 中添加时,可使用它按容器 ID 进行查找
1.在任何给定的时间点,只允许一个 FragmentManager 控制 fragment 返回堆栈。
2.如果应用在屏幕上同时显示多个同级 fragment,或者应用使用子 fragment,
则必须指定一个 FragmentManager 来处理应用的主要导航。
3.如需在 fragment 事务内定义主要导航 fragment,请对事务调用 setPrimaryNavigationFragment() 方法,
并传入一个 fragment 的实例,该 fragment 的 childFragmentManager 应具有主要控制权。
4.将导航结构视为一系列层,其中 activity 作为最外层,封装下面的每一层子 fragment。
每一层都必须有一个主要导航 fragment。当发生返回事件时,最内层控制导航行为。
一旦最内层再也没有可从其弹回的 fragment 事务,控制权就会向外回一层,此过程会一直重复,直至到达 activity 为止。
5.当同时显示两个或更多 fragment 时,其中只有一个可以是主要导航 fragment。
6.如果将某个 fragment 设为主要导航 fragment,会移除对先前 fragment 的指定。在上例中,
如果您将详情 fragment 设为主要导航 fragment,就会移除对主 fragment 的指定。
支持多个返回堆栈
在某些情况下,您的应用可能需要支持多个返回堆栈。一个常见示例是,您的应用使用底部导航栏。
FragmentManager 可让您通过 saveBackStack() 和 restoreBackStack() 方法支持多个返回堆栈。
这两种方法使您可以通过保存一个返回堆栈并恢复另一个返回堆栈来在返回堆栈之间进行交换。
saveBackStack() 的工作方式类似于使用可选 name 参数调用 popBackStack():
弹出指定事务以及堆栈上在此之后的所有事务。不同之处在于 saveBackStack()
会保存弹出事务中所有 fragment 的状态。
例如,假设您之前使用 addToBackStack() 提交 FragmentTransaction,从而将 fragment 添加到返回堆栈
1 2 3 4 5 6 7
supportFragmentManager.beginTransaction() .replace(R.id.fragment_container, ExampleFragment.class, null) // setReorderingAllowed(true) and the optional string argument for // addToBackStack() are both required if you want to use saveBackStack(). .setReorderingAllowed(true) .addToBackStack("replacement") .commit();
在这种情况下,您可以通过调用 saveState() 来保存此 fragment 事务和 ExampleFragment 的状态:
请注意,在 activity 中设置 FragmentFactory 会替换整个 activity 的 fragment 层次结构中
fragment 的创建。换句话说,您添加的任何子 fragment 的 childFragmentManager
都会使用此处设置的自定义 fragment 工厂,除非在较低的级别被替换
publicstaticclassExampleFragmentextendsFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.example_fragment, container, false); } }