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
相关产品推荐
相关产品推荐

