简体   繁体   English

如何在 Jetpack Compose Android 的 LazyColumn 中显示项目视图的动画

[英]How to show animate an item view in LazyColumn on Jetpack Compose Android

I have a list of items in lazy column view.我在惰性列视图中有一个项目列表。

How we can show animation when we are removing the one item from the list.当我们从列表中删除一项时,我们如何显示 animation。

I need to animate the view which is getting deleted.我需要为被删除的视图设置动画。 The delete operation is done by pressing the delete icon inside the view.删除操作是通过按下视图内的删除图标来完成的。

I tried with AnimationVisibility and its not working as expected.我尝试了AnimationVisibility ,但它没有按预期工作。

It is not officially supported yet but they are working on it.它尚未得到官方支持,但他们正在努力。 You can probably achieve it but in a hacky way.您可能可以实现它,但以一种 hacky 方式。

When your list updates, your composable is recreated and it doesn't support animations for items yet, so you have to add a boolean variable on your item and change the value when it's "deleted" instead of removing it from the list.当您的列表更新时,您的可组合项会重新创建,并且它还不支持项目的动画,因此您必须在项目上添加一个 boolean 变量并在它“删除”时更改值,而不是将其从列表中删除。 Once the updated list is shown, you can animate the item being removed with a delay and then update the list without it once the animation is over.显示更新后的列表后,您可以对要删除的项目进行动画处理,然后在 animation 结束后更新没有它的列表。

I have not personally tested this method so it might not work as expected but that's the only way I can think of with lazy lists not supporting update animations.我没有亲自测试过这种方法,所以它可能无法按预期工作,但这是我能想到的唯一方法,因为惰性列表不支持更新动画。

Like what YASAN said, I was able to produce 'slideOut' + 'fadeOut' animation on LazyColumn item using AnimatedVisibility by simply adding isVisible properties on DataClass of your item and wrap your item view in AnimatedVisibility Composable.就像YASAN所说的那样,我能够使用AnimatedVisibility在 LazyColumn 项目上生成 'slideOut' + 'fadeOut' animation,只需在项目的 DataClass 上添加isVisible属性并将项目视图包装在AnimatedVisibility Composable 中。 Since that api is still in experimental please be careful.由于 api 仍处于实验阶段,请小心。

For you reference if you or someone else might look for it I'm gonna drop my snippet here.供您参考,如果您或其他人可能会寻找它,我将把我的片段放在这里。

For the LazyColumn对于LazyColumn

LazyColumn {
    items(
        items = notes,
        key = { item: Note -> item.id }
    ) { item ->
        AnimatedVisibility(
            visible = item.isVisible,
            exit = fadeOut(
                animationSpec = TweenSpec(200, 200, FastOutLinearInEasing)
            )
        ) {
            ItemNote(
                item
            ) {
                notes = changeNoteVisibility(notes, it)
            }
        }
    }
}

And for the Item Composable对于可组合项目

@ExperimentalAnimationApi
@ExperimentalMaterialApi
@Composable
fun ItemNote(
    note: Note,
    onSwipeNote: (Note) -> Unit
) {
    val iconSize = (-68).dp
    val swipeableState = rememberSwipeableState(0)
    val iconPx = with(LocalDensity.current) { iconSize.toPx() }
    val anchors = mapOf(0f to 0, iconPx to 1)

    val coroutineScope = rememberCoroutineScope()

    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(75.dp)
            .swipeable(
                state = swipeableState,
                anchors = anchors,
                thresholds = { _, _ -> FractionalThreshold(0.5f) },
                orientation = Orientation.Horizontal
            )
            .background(Color(0xFFDA5D5D))
    ) {
        Box(
            modifier = Modifier
                .fillMaxHeight()
                .align(Alignment.CenterEnd)
                .padding(end = 10.dp)
        ) {
            IconButton(
                modifier = Modifier.align(Alignment.Center),
                onClick = {
                    Log.d("Note", "Deleted")
                    coroutineScope.launch {
                        onSwipeNote(note)
                    }
                }
            ) {
                Icon(
                    Icons.Default.Delete,
                    contentDescription = "Delete this note",
                    tint = Color.White
                )
            }
        }

        AnimatedVisibility(
            visible = note.isVisible,
            exit = slideOutHorizontally(
                targetOffsetX = { -it },
                animationSpec = TweenSpec(200, 0, FastOutLinearInEasing)
            )
        ) {
            ConstraintLayout(
                modifier = Modifier
                    .offset { IntOffset(swipeableState.offset.value.roundToInt(), 0) }
                    .fillMaxHeight()
                    .fillMaxWidth()
                    .background(Color.White)
            ) {
                val (titleText, contentText, divider) = createRefs()

                Text(
                    modifier = Modifier.constrainAs(titleText) {
                        top.linkTo(parent.top, margin = 12.dp)
                        start.linkTo(parent.start, margin = 18.dp)
                        end.linkTo(parent.end, margin = 18.dp)
                        width = Dimension.fillToConstraints
                    },
                    text = note.title,
                    fontSize = 16.sp,
                    fontWeight = FontWeight(500),
                    textAlign = TextAlign.Start
                )

                Text(
                    modifier = Modifier.constrainAs(contentText) {
                        bottom.linkTo(parent.bottom, margin = 12.dp)
                        start.linkTo(parent.start, margin = 18.dp)
                        end.linkTo(parent.end, margin = 18.dp)
                        width = Dimension.fillToConstraints
                    },
                    text = note.content,
                    textAlign = TextAlign.Start
                )

                Divider(
                    modifier = Modifier.constrainAs(divider) {
                        start.linkTo(parent.start)
                        end.linkTo(parent.end)
                        bottom.linkTo(parent.bottom)
                        width = Dimension.fillToConstraints
                    },
                    thickness = 1.dp,
                    color = Color.DarkGray
                )
            }
        }
    }
}

Also the data class Note还有数据 class Note

data class Note(
    var id: Int,
    var title: String = "",
    var content: String = "",
    var isVisible: Boolean = true
)

If you've used the RecyclerView widget, you'll know that it animates item changes automatically.如果您使用过 RecyclerView 小部件,您就会知道它会自动为项目更改设置动画。 The Lazy layouts do not yet provide that functionality, which means that item changes cause an instant 'snap'. Lazy 布局尚未提供该功能,这意味着项目更改会导致即时“快照”。 You can follow this bug to track any changes for this feature.您可以按照此错误跟踪此功能的任何更改。

Source: https://developer.android.com/jetpack/compose/lists#item-animations资料来源: https://developer.android.com/jetpack/compose/lists#item-animations

Check the status here: https://issuetracker.google.com/issues/150812265在此处查看状态: https://issuetracker.google.com/issues/150812265

Experimental ability to animate Lazy lists item positions was added.添加了动画延迟列表项目位置的实验能力。 There is a new modifier available within LazyItemScope called Modifier.animateItemPlacement() . LazyItemScope 中有一个新的修饰符,称为Modifier.animateItemPlacement() Usage example:使用示例:

    var list by remember { mutableStateOf(listOf("A", "B", "C")) }
    LazyColumn {
        item {
            Button(onClick = { list = list.shuffled() }) {
                Text("Shuffle")
            }
        }
        items(list, key = { it }) {
            Text("Item $it", Modifier.animateItemPlacement())
        }
    }

    When you provide a key via `LazyListScope.item` or `LazyListScope.items` this modifier will enable item reordering animations. Aside from item reordering all other position changes caused by events like arrangement or alignment changes will also be animated.

If you implement compose Version 1.1.0-beta03 .如果您实施compose版本 1.1.0-beta03 Now we have a new way on how we can animate items.现在我们有了一种新的方式来为项目设置动画。

Working example in this link with swipeToDismiss.此链接中使用 swipeToDismiss 的工作示例。

Also you may have a look on this example posted by Google. 您也可以查看 Google 发布的这个示例。

I'm just playing around but maybe something like this will help while they built out the proper solution.我只是在玩,但也许这样的事情会在他们建立正确的解决方案时有所帮助。

    @Composable
fun <T> T.AnimationBox(
    enter: EnterTransition = expandVertically() + fadeIn(),
    exit: ExitTransition = fadeOut() + shrinkVertically(),
    content: @Composable T.() -> Unit
) {
    val state = remember {
        MutableTransitionState(false).apply {
            // Start the animation immediately.
            targetState = true
        }
    }

    AnimatedVisibility(
        visibleState = state,
        enter = enter,
        exit = exit
    ) { content() }
}


LazyColumn(
  state = lazyState
) {
    item {
        AnimationBox {
            Item(text = "TEST1!")
        }
        AnimationBox {
            Item(text = "TEST2!")
        }
    }
}

I have created a gist where I solve the problem for animating adding items to a LazyColumn.我创建了一个要点,在其中解决了将项目添加到 LazyColumn 的动画问题。 Really easy to add item removal animation too.真的很容易添加项目删除 animation 太。 I hope you find it useful希望对你有帮助

https://gist.github.com/EudyContreras/f91b20c49552e02607816b3aea6e7f43 https://gist.github.com/EudyContreras/f91b20c49552e02607816b3aea6e7f43

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM