gpt4 book ai didi

android - SwipeToDismiss 在带有动画的 LazyColumn 内

转载 作者:行者123 更新时间:2023-12-04 23:54:50 28 4
gpt4 key购买 nike

我正在努力实现类似 this 的目标但使用 Jetpack Compose。换句话说,滑动删除就像我们在 RecyclerView 中所做的那样。与 ItemTouchHelperclass DiffCallBack : DiffUtil.ItemCallback<RvModel>()我们在哪里可以看到enter - exit animations然后列表在插入或删除项目的位置优雅地向上或向下移动。

这是我试过的:

LazyColumn(state = listState) {
items(products, {listItem:InventoryEntity -> listItem.inventoryId}) { item ->
var unread by remember { mutableStateOf(false) }
val dismissState = rememberDismissState(
confirmStateChange = {
if (it == DismissValue.DismissedToEnd) unread = !unread
it != DismissValue.DismissedToEnd
}
)
val isDismissed = dismissState.isDismissed(DismissDirection.EndToStart)

if (dismissState.isDismissed(DismissDirection.EndToStart)){
LaunchedEffect(Unit) {
delay(300)
viewModel.deleteProduct(item.inventoryId)
}

}

var itemAppeared by remember { mutableStateOf(!columnAppeared) }
LaunchedEffect(Unit) {
itemAppeared = true
}

AnimatedVisibility(
visible = itemAppeared && !isDismissed,
exit = shrinkVertically(
animationSpec = tween(
durationMillis = 300,
)
),
enter = expandVertically(
animationSpec = tween(
durationMillis = 300
)
)
) {
SwipeToDismiss(
state = dismissState,
modifier = Modifier.padding(vertical = 4.dp),
directions = setOf(
DismissDirection.StartToEnd,
DismissDirection.EndToStart
),
dismissThresholds = { direction ->
FractionalThreshold(if (direction == DismissDirection.StartToEnd) 0.25f else 0.5f)
},
background = {
val direction =
dismissState.dismissDirection ?: return@SwipeToDismiss
val color by animateColorAsState(
when (dismissState.targetValue) {
DismissValue.Default -> Color.LightGray
DismissValue.DismissedToEnd -> Color.Green
DismissValue.DismissedToStart -> Color.Red
}
)
val alignment = when (direction) {
DismissDirection.StartToEnd -> Alignment.CenterStart
DismissDirection.EndToStart -> Alignment.CenterEnd
}
val icon = when (direction) {
DismissDirection.StartToEnd -> Icons.Default.Done
DismissDirection.EndToStart -> Icons.Default.Delete
}
val scale by animateFloatAsState(
if (dismissState.targetValue == DismissValue.Default) 0.75f else 1f
)

Box(
Modifier
.fillMaxSize()
.background(color)
.padding(horizontal = 20.dp),
contentAlignment = alignment
) {
Icon(
icon,
contentDescription = "Localized description",
modifier = Modifier.scale(scale)
)
}
},
dismissContent = {
Card(
elevation = animateDpAsState(
if (dismissState.dismissDirection != null) 4.dp else 0.dp
).value
) {
ProductRow(product = item, number = item.inventoryId)
}
}
)
}
}
}

尽管它有效。滚动不流畅,当我向上滚动时它会跳到顶部。实现此功能的正确方法是什么?

最佳答案

最近 google 宣布了 compose 版本 1.1.0-beta03。现在我们有了一种新的方法来为项目设置动画。他们引入了一个新的修饰符:Modifier.animateItemPlacement()。您可以在 this link 中找到最新的 compose 版本.

我将尝试用最少的代码发布一个示例,以便您可以重现它并了解如何在 LazyColumn 中使用动画实现 SwipeToDismiss。

数据类存储信息:

data class DataSet(
val itemId: Int,
val itemName: String,
val itemQty: String
)

比较列表项的比较器:

private val ListComparator = Comparator<DataSet> { left, right ->
left.itemId.compareTo(right.itemId)
}

我们每个项目所在的行:

@Composable
fun ItemRow(
modifier: Modifier = Modifier,
product: DataSet,
number: Int
) {

Card(
shape = RoundedCornerShape(4.dp),
modifier = modifier
.padding(8.dp)
.fillMaxWidth(),
backgroundColor = Color.LightGray
) {
Row(modifier = modifier) {
Text(
text = "$number.", modifier = Modifier
.weight(2f)
.padding(start = 8.dp, end = 4.dp)
)
Text(
text = product.itemName, modifier = Modifier
.weight(10f)
.padding(end = 4.dp)
)
Text(
text = product.itemQty, modifier = Modifier
.weight(2f)
.padding(end = 4.dp)
)
}
}
}

将所有内容组合到我们的可组合项中:

@ExperimentalMaterialApi
@ExperimentalFoundationApi
@Composable
fun helloWorld() {
var list by remember { mutableStateOf(listOf<DataSet>()) }

val comparator by remember { mutableStateOf(ListComparator) }

LazyColumn {
item {
Button(onClick = {
list = list + listOf(DataSet((0..1111).random(), "A random item", "100"))
}) {
Text("Add an item to the list")
}
}

val sortedList = list.sortedWith(comparator)

items(sortedList, key = { it.itemId }) { item ->
val dismissState = rememberDismissState()
if (dismissState.isDismissed(DismissDirection.EndToStart)) {
list = list.toMutableList().also { it.remove(item) } // remove
}
SwipeToDismiss(
state = dismissState,
modifier = Modifier
.padding(vertical = 1.dp)
.animateItemPlacement(),
directions = setOf(DismissDirection.StartToEnd, DismissDirection.EndToStart),
dismissThresholds = { direction ->
FractionalThreshold(if (direction == DismissDirection.StartToEnd) 0.25f else 0.5f)
},
background = {
val direction = dismissState.dismissDirection ?: return@SwipeToDismiss
val color by animateColorAsState(
when (dismissState.targetValue) {
DismissValue.Default -> Color.LightGray
DismissValue.DismissedToEnd -> Color.Green
DismissValue.DismissedToStart -> Color.Red
}
)
val alignment = when (direction) {
DismissDirection.StartToEnd -> Alignment.CenterStart
DismissDirection.EndToStart -> Alignment.CenterEnd
}
val icon = when (direction) {
DismissDirection.StartToEnd -> Icons.Default.Done
DismissDirection.EndToStart -> Icons.Default.Delete
}
val scale by animateFloatAsState(
if (dismissState.targetValue == DismissValue.Default) 0.75f else 1f
)

Box(
Modifier
.fillMaxSize()
.background(color)
.padding(horizontal = 20.dp),
contentAlignment = alignment
) {
Icon(
icon,
contentDescription = "Localized description",
modifier = Modifier.scale(scale)
)
}
},
dismissContent = {
Card(
elevation = animateDpAsState(
if (dismissState.dismissDirection != null) 4.dp else 0.dp
).value
) {
ItemRow(
product = item,
number = item.itemId
)
}
}
)
}
}
}

作为引用,另请参阅有关如何使用 Modifier.animateItemPlacement() 的其他方法,您可以查看 this example从谷歌发布。

关于android - SwipeToDismiss 在带有动画的 LazyColumn 内,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70066048/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com