我在 Compose 中有一个 HorizontalPager,用户可以删除 Pager 的任何项目。当用户删除任何项目时,我希望其他元素通过动画移动到空白位置。
这实际上是 RecylerView(ListAdapter) 的默认动画,甚至 LazyColumn 使用 animateItem 来管理它,或者使用已弃用的名称 animateItemPlacement。
我想知道如何在 HorizontalPager 中实现相同的概念?
@Composable
fun HomePageBanner(
bannerList: List<BannerUIModel>,
modifier: Modifier = Modifier,
onButtonClicked: (index: Int) -> Unit = {},
onItemRemoved: (index: Int) -> Unit = {},
) {
val pageCount = bannerList.size
val pagerState = rememberPagerState(pageCount = { pageCount })
HorizontalPager(
state = pagerState,
modifier = modifier,
contentPadding = PaddingValues(start = 16.dp, end = 12.dp),
pageSpacing = 0.dp,
) { index ->
val banner = bannerList[index]
BannerCardItem(
bannerItem = banner,
modifier = Modifier.fillMaxWidth().padding(12.dp),
onButtonClicked = { onButtonClicked(index) },
onItemRemoved = {
// When this is called, the item will be removed
// and HomePageBanner will be called with the new list
onItemRemoved(index)
},
)
}
}
Modifier.animateItem()
是 LazyItemScope
中定义的作用域修饰符。没有默认的 PagerScope 修饰符,实际上 PagerScope 中还没有任何东西。您也可以针对寻呼机提出功能请求。
/**
* Receiver scope for [Pager].
* Note: This is empty now, but we may add new members in the future if needed.
*/
sealed interface PagerScope
internal object PagerScopeImpl : PagerScope
但是您可以将捕捉行为应用于
LazyRow/Column
,您可以像 Pager
那样捕捉并使用 Modifer.animateItem()
@Preview
@Composable
fun LazyRowSnapAndDeleteAnimation() {
val viewModel = remember {
MyViewModel()
}
val lazyListState = rememberLazyListState()
Column(
modifier = Modifier.fillMaxSize().background(backgroundColor).padding(vertical = 32.dp)
) {
val list = viewModel.list
LazyRow(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(start = 16.dp, end = 12.dp),
flingBehavior = rememberSnapFlingBehavior(lazyListState, snapPosition = SnapPosition.Start),
state = lazyListState
) {
itemsIndexed(
items = list,
key = { _, item ->
item.id
}
) { page, item ->
Column(
modifier = Modifier
.animateItem()
.fillParentMaxWidth()
.height(200.dp)
.shadow(2.dp, RoundedCornerShape(16.dp))
.background(Color.White)
.padding(32.dp)
) {
Text("Item")
Button(
modifier = Modifier.fillMaxWidth(),
onClick = {
viewModel.removeItem(page)
}
) {
Text("Remove ${item.value}")
}
}
}
}
}
}
如果使用 LazyRow 是不可能的,您可以编写一个修改器来实现,但这并不容易,并且有一些情况需要处理。基本上你需要设置 Modifier.layout 与层,但由于 HorizontalPager 具有固定的页面大小,不要让项目收缩,你还需要处理项目滚动。另外,在您的情况下,由于 ContentPadding,您还应该处理上一个和下一个项目的情况。如果需要,我可以为此发布一个示例。