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

SharedTransitionLayout与ConstraintLayout搭配引发崩溃求助

问题:SharedTransitionLayout与ConstraintLayout组合导致崩溃

应用中使用SharedTransitionLayout包裹NavHost,此前导航页面的Composable未使用ConstraintLayout。近期在部分导航页面引入ConstraintLayout后出现崩溃,以下是崩溃日志及导航宿主结构代码:

崩溃日志

FATAL EXCEPTION: main
java.lang.IllegalStateException: Error: Placement happened before lookahead.
    at androidx.compose.ui.internal.InlineClassHelperKt.throwIllegalStateException(InlineClassHelper.kt:26)
    at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.placeSelf-MLgxB_4(LayoutNodeLayoutDelegate.kt:2110)
    at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.placeAt-f8xVGno(LayoutNodeLayoutDelegate.kt:765)
    at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:35)
    at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:621)
    at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50$default(Placeable.kt:259)
    at androidx.constraintlayout.compose.Measurer.performLayout(ConstraintLayout.kt:1321)
    at androidx.constraintlayout.compose.ConstraintLayoutKt$rememberConstraintLayoutMeasurePolicy$1$measurePolicy$1$measure$1.invoke(ConstraintLayout.kt:123)
    at androidx.constraintlayout.compose.ConstraintLayoutKt$rememberConstraintLayoutMeasurePolicy$1$measurePolicy$1$measure$1.invoke(ConstraintLayout.kt:122)
    at androidx.compose.ui.node.LookaheadCapablePlaceable$layout$1.placeChildren(LookaheadDelegate.kt:223)
    at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildrenBlock$1.invoke(LayoutNodeLayoutDelegate.kt:429)
    at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildrenBlock$1.invoke(LayoutNodeLayoutDelegate.kt:424)
    at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:503)
    at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:502)
    at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:258)
    at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
    at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutSnapshotReads$ui_release(OwnerSnapshotObserver.kt:83)
    at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.layoutChildren(LayoutNodeLayoutDelegate.kt:457)
    at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.onNodePlaced$ui_release(LayoutNodeLayoutDelegate.kt:627)
    at androidx.compose.ui.node.InnerNodeCoordinator.onAfterPlaceAt(InnerNodeCoordinator.kt:182)
    at androidx.compose.ui.node.InnerNodeCoordinator.placeAt-f8xVGno(InnerNodeCoordinator.kt:169)
    at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:35)
    at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:621)
    at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50$default(Placeable.kt:259)
    at androidx.compose.foundation.layout.WrapContentNode$measure$1.invoke(Size.kt:1019)
    at androidx.compose.foundation.layout.WrapContentNode$measure$1.invoke(Size.kt:1011)
    at androidx.compose.ui.node.LookaheadCapablePlaceable$layout$1.placeChildren(LookaheadDelegate.kt:223)
    at androidx.compose.ui.node.LayoutModifierNodeCoordinator.onAfterPlaceAt(LayoutModifierNodeCoordinator.kt:270)
    at androidx.compose.ui.node.LayoutModifierNodeCoordinator.placeAt-f8xVGno(LayoutModifierNodeCoordinator.kt:247)
    at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:35)
    at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative(Placeable.kt:609)
    at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative$default(Placeable.kt:232)
    at androidx.compose.foundation.layout.FillNode$measure$1.invoke(Size.kt:704)
    at androidx.compose.foundation.layout.FillNode$measure$1.invoke(Size.kt:703)
    at androidx.compose.ui.node.LookaheadCapablePlaceable$layout$1.placeChildren(LookaheadDelegate.kt:223)
    at androidx.compose.ui.node.LayoutModifierNodeCoordinator.onAfterPlaceAt(LayoutModifierNodeCoordinator.kt:270)
    at androidx.compose.ui.node.LayoutModifierNodeCoordinator.placeAt-f8xVGno(LayoutModifierNodeCoordinator.kt:247)

导航宿主结构代码

SharedTransitionLayout{
        NavHost(
            modifier = modifier.background(color = colorResource(id = R.color.htl_background)),
            navController = navController,
            startDestination = SelectRoomDestination.SELECT_ROOM_SCREEN.name
        ) {
            
            composable(
                "plan",
            ) {
                // 使用ConstraintLayout的页面
            }
            
            composable(
                "listing"
            ) {
                // 使用ConstraintLayout的页面
            }
            composable("detail") {
                // 使用ConstraintLayout的页面
            }
        }
    }

解决方案

  • 升级依赖版本:该问题属于ConstraintLayout Compose与SharedTransitionLayout的兼容性问题,建议将androidx.constraintlayout:constraintlayout-compose升级至1.1.0-beta04及以上版本,同时确保Compose核心依赖(如androidx.compose.ui:ui)版本匹配。
  • 禁用Lookahead布局:若暂时无法升级依赖,可在使用ConstraintLayout的页面添加Modifier.lookaheadSize(IntSize.Zero)禁用Lookahead,避免布局冲突:
    ConstraintLayout(
        modifier = Modifier.lookaheadSize(IntSize.Zero)
    ) {
        // 布局内容
    }
    
  • 临时替换布局容器:如果上述方法无效,可暂时用Column、Row、Box等基础布局替代ConstraintLayout,待依赖兼容问题修复后再切换回来。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 13:27:04