使用目标库时共享元素转换 - Compose Android

问题描述 投票:0回答:1

Destination 这个库是维护屏幕的救星,因为它删除了很多样板,但现在我想使用它的共享元素转换,并且我正在努力构建它,因为我应该在参数中传递什么。

我们可以传递字符串、布尔值、序列化类,但是需要将什么传递到下一个屏幕以实现过渡动画

android kotlin navigation android-jetpack-compose
1个回答
0
投票

只要两个屏幕中的

Int
String
中的
Double
键匹配,您就可以通过
Float
rememberSharedContentState(key: Any)
sharedElement
sharedBounds
或任何课程。

但是使用唯一的密钥是谷歌建议的

在处理复杂的共享元素时,最好的做法是 创建一个不是字符串的键,因为字符串可能容易出错 匹配。每个键必须是唯一的才能发生匹配。例如, 在 Jetsnack 中,我们有以下共享元素:

data class SnackSharedElementKey(
    val snackId: Long,
    val origin: String,
    val type: SnackSharedElementType
)

enum class SnackSharedElementType {
    Bounds,
    Image,
    Title,
    Tagline,
    Background
}


@Composable
fun SharedElementUniqueKey() {
    // ...
            Box(
                modifier = Modifier
                    .sharedElement(
                        rememberSharedContentState(
                            key = SnackSharedElementKey(
                                snackId = 1,
                                origin = "latest",
                                type = SnackSharedElementType.Image
                            )
                        ),
                        animatedVisibilityScope = this@AnimatedVisibility
                    )
            )
            // ...
}

我用 String 键制作了一个示例,通过导航从 LazyColumn 转换到 HorizontalPager,但正如您所看到的,两个屏幕都不依赖于 NavController。

enter image description here

@Composable
private fun DetailsScreen(
    snack: SnackItem,
    sharedTransitionScope: SharedTransitionScope,
    animatedContentScope: AnimatedContentScope,
    onClick: (String) -> Unit,
) {

    var selectedIndex by remember {
        mutableStateOf(listSnacks.indexOf(snack).coerceAtLeast(0))
    }
    with(sharedTransitionScope) {

        val pagerState = rememberPagerState(
            initialPage = selectedIndex,
            pageCount = {
                listSnacks.size
            }
        )

        HorizontalPager(
            state = pagerState,
            pageSpacing = 16.dp
        ) { page ->

            selectedIndex = page
            val currentSnack = listSnacks[page]

            Column(
                Modifier
                    .fillMaxSize()
                    .clickable(
                        interactionSource = remember {
                            MutableInteractionSource()
                        },
                        indication = null
                    ) {
                        onClick("home")
                    }
            ) {
                Image(
                    painterResource(id = currentSnack.image),
                    contentDescription = currentSnack.description,
                    contentScale = ContentScale.Crop,
                    modifier = Modifier
                        .sharedElement(
                            sharedTransitionScope.rememberSharedContentState(key = "image-$selectedIndex"),
                            animatedVisibilityScope = animatedContentScope
                        )
                        .aspectRatio(1f)
                        .fillMaxWidth()
                )
                Text(
                    currentSnack.name, fontSize = 38.sp,
                    modifier =
                    Modifier
                        .sharedBounds(
                            sharedTransitionScope.rememberSharedContentState(key = "text-$selectedIndex"),
                            animatedVisibilityScope = animatedContentScope,
                        )
                )
            }
        }
    }
}

@Composable
private fun HomeScreen(

    scrollState: LazyListState,
    sharedTransitionScope: SharedTransitionScope,
    animatedContentScope: AnimatedContentScope,
    onClick: (String) -> Unit,
) {

    var isDetailSelected by remember {
        mutableStateOf(false)
    }

    with(sharedTransitionScope) {
        Column {

            TopAppBar(
                title = {
                    Text("Title")
                },
                backgroundColor = Color.Black,
                contentColor = Color.White,
                modifier = if (isDetailSelected) Modifier
                else Modifier.renderInSharedTransitionScopeOverlay()
            )
            LazyColumn(
                modifier = Modifier
                    .fillMaxSize(),
                contentPadding = PaddingValues(8.dp),
                state = scrollState,
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                itemsIndexed(listSnacks) { index, item ->
                    Row(
                        Modifier.clickable(
                            interactionSource = remember {
                                MutableInteractionSource()
                            },
                            indication = null
                        ) {
                            isDetailSelected = true
                            onClick("details/$index")
                        }
                    ) {
                        Spacer(modifier = Modifier.width(8.dp))
                        Image(
                            painterResource(id = item.image),
                            contentDescription = item.description,
                            contentScale = ContentScale.Crop,
                            modifier = Modifier
                                .sharedElement(
                                    sharedTransitionScope.rememberSharedContentState(key = "image-$index"),
                                    animatedVisibilityScope = animatedContentScope
                                )
                                .size(120.dp)
                        )
                        Spacer(modifier = Modifier.width(8.dp))
                        Text(
                            item.name, fontSize = 18.sp,
                            modifier = Modifier
                                .align(Alignment.CenterVertically)
                                .sharedBounds(
                                    sharedTransitionScope.rememberSharedContentState(key = "text-$index"),
                                    animatedVisibilityScope = animatedContentScope
                                )
                        )
                    }
                }
            }
        }
    }
}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.