You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含ComposeView的Fragment配置MaterialSharedAxis返回时崩溃如何解决

问题现象

存在如下TimelineFragment实现:

class TimelineFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val axis = MaterialSharedAxis.Z

        val forward = MaterialSharedAxis(axis, true)
        val backward = MaterialSharedAxis(axis, false)

        enterTransition = forward
        exitTransition = forward
        reenterTransition = backward
        returnTransition = backward
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ) = ComposeView(requireActivity()).apply { 
        setContent { 
            Text(text = "Testing")
        }
    }
}

从该Fragment点击返回按钮时应用崩溃,核心报错为:

java.lang.UnsupportedOperationException: Cannot add views to ComposeView; only Compose content is supported

完整崩溃堆栈:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.farmersbyte.agripro, PID: 8524
java.lang.UnsupportedOperationException: Cannot add views to ComposeView; only Compose content is supported
    at androidx.compose.ui.platform.AbstractComposeView.checkAddView(ComposeView.android.kt:202)
    at androidx.compose.ui.platform.AbstractComposeView.addView(ComposeView.android.kt:346)
    at androidx.transition.TransitionUtils.createViewBitmap(TransitionUtils.java:138)
    at androidx.transition.TransitionUtils.copyViewImage(TransitionUtils.java:64)
    at androidx.transition.Visibility.onDisappear(Visibility.java:404)
    at androidx.transition.Visibility.createAnimator(Visibility.java:257)
    at androidx.transition.Transition.createAnimators(Transition.java:744)
    at androidx.transition.TransitionSet.createAnimators(TransitionSet.java:480)
    at androidx.transition.TransitionSet.createAnimators(TransitionSet.java:480)
    at androidx.transition.Transition.playTransition(Transition.java:1808)
    at androidx.transition.TransitionManager$MultiListener.onPreDraw(TransitionManager.java:300)
    at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:1088)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2745)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1721)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7598)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
    at android.view.Choreographer.doCallbacks(Choreographer.java:790)
    at android.view.Choreographer.doFrame(Choreographer.java:725)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:951)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

已知触发条件:

  • 项目使用Jetpack Navigation组件实现Fragment导航
  • 仅当Fragment设置了MaterialSharedAxis转场动画、执行返回按压操作时触发崩溃
  • Compose版本为1.0.1时无异常,升级到1.1.0及以上版本后出现该崩溃
崩溃原因

Compose 1.1.0及以上版本收紧了ComposeView的能力限制,直接禁止通过addView方法往ComposeView中添加View子节点,调用就会抛出UnsupportedOperationException。
而MaterialSharedAxis属于基于View系统实现的Visibility类转场,执行返回/退出动画的消失逻辑时,会调用TransitionUtils.copyViewImage方法,尝试在当前Fragment的根View上添加一个临时的视图快照节点来实现转场视觉效果。当Fragment直接返回ComposeView作为根节点时,这个addView操作就会直接触发崩溃。
原代码还存在两个不规范的点:

  • 创建ComposeView时传入了requireActivity()作为Context,应该使用LayoutInflater自带的上下文,避免主题不匹配、内存泄漏问题
  • 没有给ComposeView设置合适的组合释放策略,容易引发Composition泄漏
修复方案

不要直接将ComposeView作为Fragment的根View返回,在外层套一层原生ViewGroup作为根容器,转场动画添加临时快照的操作会作用在这层原生容器上,不会触发ComposeView的限制。
修复后的代码示例:

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
) = FrameLayout(inflater.context).apply {
    // 外层用原生FrameLayout作为根布局,承载转场逻辑
    addView(ComposeView(context).apply {
        // 设置正确的Composition释放策略,绑定Fragment视图生命周期
        setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
        setContent {
            Text(text = "Testing")
        }
    })
}

该方案不需要修改转场动画逻辑,也不需要降级Compose版本,兼容所有1.1.0及以上版本的Compose。

内容的提问来源于stack exchange,提问作者Nabeel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 02:36:51