如何在 Jetpack Compose 中的 HorizontalPager 中删除项目时添加动画

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

我在 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)
            },
        )
    }
}
android kotlin android-jetpack-compose android-viewpager android-jetpack-compose-pager
1个回答
0
投票

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

动画 LazyRow 项目更改

enter image description here

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

HorizontalPager 项目更改动画

如果使用 LazyRow 是不可能的,您可以编写一个修改器来实现,但这并不容易,并且有一些情况需要处理。基本上你需要设置 Modifier.layout 与层,但由于 HorizontalPager 具有固定的页面大小,不要让项目收缩,你还需要处理项目滚动。另外,在您的情况下,由于 ContentPadding,您还应该处理上一个和下一个项目的情况。如果需要,我可以为此发布一个示例。

© www.soinside.com 2019 - 2024. All rights reserved.