Compose实现的Fragment结合Fragment Navigation能否实现共享元素转场?
这种场景完全可行,核心是将Compose元素与Fragment Navigation的共享元素机制绑定,通过Compose的Modifier.sharedElement和Fragment转场API配合实现。以下是具体实现步骤和示例:
1. 配置Navigation转场基础
确保Navigation组件版本在2.4.0+,在导航图nav_graph.xml中为跳转动作配置共享元素转场:
<fragment android:id="@+id/fragmentA" android:name="com.example.FragmentA"> <action android:id="@+id/action_fragmentA_to_bottomSheetFragmentB" app:destination="@id/bottomSheetFragmentB" app:sharedElementsEnterTransition="@transition/change_bounds" app:sharedElementsReturnTransition="@transition/change_bounds"/> </fragment> <fragment android:id="@+id/bottomSheetFragmentB" android:name="com.example.BottomSheetFragmentB"/>
2. 在Compose布局标记共享元素
两个Fragment的Compose内容中,用相同的唯一key标记需要共享的元素:
FragmentA的Compose内容
@Composable fun FragmentAContent(onNavigate: (String) -> Unit) { val sharedKey = "shared_avatar" Box(modifier = Modifier.fillMaxSize()) { Image( painter = painterResource(R.drawable.avatar), contentDescription = "Avatar", modifier = Modifier .size(80.dp) .sharedElement(key = sharedKey, rememberSharedElementState()) .clickable { onNavigate(sharedKey) } ) } }
BottomSheetFragmentB的Compose内容
@Composable fun BottomSheetContent(sharedKey: String) { Box(modifier = Modifier.fillMaxSize()) { Image( painter = painterResource(R.drawable.avatar), contentDescription = "Avatar", modifier = Modifier .size(160.dp) .align(Alignment.TopCenter) .sharedElement(key = sharedKey, rememberSharedElementState()) ) } }
3. 在Fragment中绑定转场逻辑
FragmentA中启动导航并传递共享元素
class FragmentA : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { setContent { FragmentAContent { sharedKey -> // 获取Compose共享元素的Node val sharedNode = LocalSharedElementRoot.current?.findNode(sharedKey) sharedNode?.let { // 构建Fragment共享元素映射 val extras = FragmentNavigatorExtras(it to sharedKey) findNavController().navigate( R.id.action_fragmentA_to_bottomSheetFragmentB, null, null, extras ) } } } } } }
BottomSheetFragmentB中接收转场
class BottomSheetFragmentB : BottomSheetDialogFragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { // 启用共享元素转场 sharedElementEnterTransition = TransitionInflater.from(requireContext()) .inflateTransition(R.transition.change_bounds) // 解决BottomSheet遮挡转场元素的问题 dialog?.window?.sharedElementsUseOverlay = false return ComposeView(requireContext()).apply { setContent { BottomSheetContent(sharedKey = "shared_avatar") } } } }
关键注意事项
- 共享元素的
key必须在两个Fragment中完全一致,这是转场匹配的核心。 - 若使用BottomSheetDialogFragment,必须设置
sharedElementsUseOverlay = false,避免转场元素被弹窗遮挡。 - 建议使用Navigation 2.5.0及以上版本,兼容性更稳定。
内容的提问来源于stack exchange,提问作者Royss
相关产品推荐
相关产品推荐

