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

通过DeepLink打开应用时SharedTransition API引发崩溃问题

DeepLink打开Compose应用崩溃:Uninitialized LayoutCoordinates问题解决

问题现象

通过通知或Widget的DeepLink打开应用时,应用直接崩溃,崩溃堆栈核心错误:

java.lang.IllegalArgumentException: Error: Uninitialized LayoutCoordinates. Please make sure when using the SharedTransitionScope composable function, the modifier passed to the child content is being used, or use SharedTransitionLayout instead.

崩溃原因

  1. 共享元素上下文缺失:直接通过DeepLink进入DefinitionScreen时,HomeScreen并未加载,导致SharedTransitionScope依赖的布局上下文未初始化。
  2. 无效的Scope传递:代码中传递的AnimatedContentScope仅在导航动画触发时有效,DeepLink直接跳转时没有触发导航动画,该Scope处于无效状态,进而导致共享元素的布局坐标无法获取。

修复方案

核心修改点

  • 移除对AnimatedContentScope的直接传递,改用SharedTransitionScope自身上下文管理共享元素状态
  • 通过路由参数标记是否来自共享跳转,仅在合法场景下启用共享元素动画
  • 确保SharedTransitionLayout的布局上下文正确绑定到所有共享元素

完整代码修改

1. 导航宿主与路由配置

@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun EnglishDictionaryNavHost(modifier: Modifier = Modifier) {
    SharedTransitionLayout(modifier = modifier) {
        val navController = rememberNavController()

        NavHost(
            modifier = modifier,
            navController = navController,
            startDestination = Home,
        ) {
            definitionScreen(
                sharedTransitionScope = this@SharedTransitionLayout,
                onNavigateBack = { navController.popBackStack() }
            )

            homeScreen(
                sharedTransitionScope = this@SharedTransitionLayout,
                onNavigateToDefinition = { word, isWotd ->
                    navController.navigate(DefinitionRoute(word, isWotd))
                }
            )
        }
    }
}

@Serializable
data object Home

@Serializable
data class DefinitionRoute(val word: String, val isWotd: Boolean = false)

2. HomeScreen与WordOfTheDay组件

fun NavGraphBuilder.homeScreen(
    sharedTransitionScope: SharedTransitionScope,
    onNavigateToDefinition: (String, Boolean) -> Unit
) {
    composable<Home> {
        HomeScreen(
            sharedTransitionScope = sharedTransitionScope,
            onNavigateToDefinition = onNavigateToDefinition
        )
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun HomeScreen(
    sharedTransitionScope: SharedTransitionScope,
    onNavigateToDefinition: (String, Boolean) -> Unit
) {
    Scaffold() { paddingValues ->
        LazyColumn(contentPadding = paddingValues) {
            item {
                WordOfTheDay(
                    sharedTransitionScope = sharedTransitionScope,
                    onNavigate = onNavigateToDefinition
                )
            }
        }
    }
}

@Composable
private fun WordOfTheDay(
    sharedTransitionScope: SharedTransitionScope,
    onNavigate: (String, Boolean) -> Unit
) {
    val word = wordOfTheDay.word
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
            .clickable { onNavigate(word, true) }
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp),
        ) {
            with(sharedTransitionScope) {
                Text(
                    text = word,
                    style = MaterialTheme.typography.headlineLarge,
                    modifier = Modifier.sharedElement(
                        rememberSharedContentState(key = word)
                    )
                )
            }
        }
    }
}

3. DefinitionScreen与TopAppBar组件

fun NavGraphBuilder.definitionScreen(
    sharedTransitionScope: SharedTransitionScope,
    onNavigateBack: () -> Unit
) {
    composable<DefinitionRoute>(deepLinks = listOf(navDeepLink {
        uriPattern = "app://com.ayitinya.englishdictionary/{word}"
    })) { backStackEntry ->
        val route = backStackEntry.toRoute<DefinitionRoute>()
        DefinitionScreen(
            sharedTransitionScope = sharedTransitionScope,
            word = route.word,
            isWotd = route.isWotd,
            onNavigateBack = onNavigateBack
        )
    }
}

@OptIn(ExperimentalMaterial3Api::class, ExperimentalPermissionsApi::class)
@Composable
private fun DefinitionScreen(
    sharedTransitionScope: SharedTransitionScope,
    word: String,
    isWotd: Boolean,
    onNavigateBack: () -> Unit
) {
    val lazyListState = rememberLazyListState()

    Scaffold(
        topBar = {
            TopAppBar(
                sharedTransitionScope = sharedTransitionScope,
                word = word,
                enableSharedTransition = isWotd,
                onNavigateBack = onNavigateBack
            )
        }
        // 原有页面内容保留
    )
}

@OptIn(ExperimentalMaterial3Api::class, ExperimentalSharedTransitionApi::class)
@Composable
private fun TopAppBar(
    sharedTransitionScope: SharedTransitionScope,
    word: String,
    enableSharedTransition: Boolean,
    onNavigateBack: () -> Unit
) {
    LargeTopAppBar(
        title = {
            if (enableSharedTransition) {
                with(sharedTransitionScope) {
                    Text(
                        text = word,
                        modifier = Modifier
                            .weight(4f)
                            .sharedElement(
                                rememberSharedContentState(key = word)
                            )
                    )
                }
            } else {
                Text(
                    text = word,
                    modifier = Modifier.weight(4f)
                )
            }
        },
        navigationIcon = {
            IconButton(onClick = onNavigateBack) {
                Icon(Icons.Default.ArrowBack, contentDescription = "返回")
            }
        }
    )
}

关键修复说明

  • 移除AnimatedContentScope参数:该Scope仅在导航动画流程中有效,DeepLink直接进入时无有效上下文,会导致布局坐标初始化失败。
  • 增加isWotd路由参数:标记是否来自HomeScreen的共享跳转,仅在该场景下启用共享元素动画,DeepLink直接进入时使用普通Text组件,避免触发未初始化的共享过渡。
  • 共享元素状态绑定:通过SharedTransitionScope自身的rememberSharedContentState创建状态,确保布局上下文正确关联。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:01:01