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

hof1towb  于 2023-01-24  发布在  Android
关注(0)|答案(7)|浏览(183)

我在惰性列视图中有一个项目列表。
当我们从列表中删除一个项目时,如何显示动画。
我需要动画视图这是越来越删除。删除操作是通过按下删除图标内的看法。

我尝试使用AnimationVisibility,但它没有按预期工作。

odopli94

odopli941#

针对合成1.1.0的更新:

动画项目的位置变化现在是可能的,但删除/插入动画仍然是不可能的,需要实现的方法,我已经解释。
要使项目位置变化具有动画效果,您只需在列表中通过key = { it.id }提供项目键并使用Modifier.animateItemPlacement()

原始答案

它还没有得到官方的支持,但是他们正在努力。你可能可以实现它,但是用一种黑客的方式。
当列表更新时,您的可组合对象将被重新创建,但它还不支持项目动画,因此您必须在项目上添加布尔变量,并在项目“删除”时更改其值,而不是将其从列表中移除。显示更新后的列表后,您可以延迟一段时间动画正在移除的项目,然后在动画结束后更新列表。
我没有亲自测试过这个方法,所以它可能不会像预期的那样工作,但这是我能想到的不支持更新动画的惰性列表的唯一方法。

b4lqfgs4

b4lqfgs42#

    • 实验性**增加了动态显示惰性列表项目位置的功能。

LazyItemScope中有一个新的修改器Modifier.animateItemPlacement()。如果您为每个项目提供唯一的key,则此修改器有效。
用法示例:

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())
    }
}

当你通过LazyListScope.itemLazyListScope.items提供一个键时,这个修饰符将启用项目重新排序动画。除了项目重新排序之外,所有其他由事件引起的位置变化,如排列或对齐变化也将被动画化。

krcsximq

krcsximq3#

正如YASAN所说,我可以使用AnimatedVisibility在LazyColumn项上生成'slideOut' + 'fadeOut'动画,只需在项的DataClass上添加isVisible属性,并将项视图 Package 在AnimatedVisibility Composable中。
如果你或其他人可能会寻找它,我会把我的片段在这里给你参考。
对于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)
            }
        }
    }
}

对于可合成物料

@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
                )
            }
        }
    }
}

同样,数据类Note

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

jbose2ul4#

我只是玩玩,但也许像这样的东西会帮助,而他们建立了适当的解决方案。

@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!")
        }
    }
}
nwlls2ji

nwlls2ji5#

如果你使用过RecyclerView widget,你就会知道它会自动为项目的变化制作动画。Lazy布局还没有提供这个功能,这意味着项目的变化会引起即时的"快照"。你可以跟踪这个bug来跟踪这个功能的任何变化。
图片来源:www.example.comhttps://developer.android.com/jetpack/compose/lists#item-animations
在此处检查状态:https://issuetracker.google.com/issues/150812265

wrrgggsh

wrrgggsh6#

如果你实现了composeVersion 1.1.0-beta 03,现在我们有了一种新的方法来动画化项目。
Working example in this link with swipeToDismiss.
Also you may have a look on this example posted by Google.

hgncfbus

hgncfbus7#

我已经创建了一个要点,我解决了动画添加项目到一个懒惰列的问题。真的很容易添加项目删除动画太多。我希望你觉得有用
https://gist.github.com/EudyContreras/f91b20c49552e02607816b3aea6e7f43

相关问题