在 Jetpack Compose 中使用动画展开和折叠 LazyColumn 项目

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

我将

stickyHeader
LazyColumn
一起使用,我想在单击标题时展开和折叠每个标题下的项目,并具有流畅的动画。我已经使用
AnimatedVisibility
实现了此行为,这对于少量项目来说效果很好。

但是,当标题下的项目数量变大(例如,超过 100 个项目)时,UI 在动画过程中开始显着滞后。

是否有更好的方法来实现这种具有更好性能的扩展和折叠行为,或者我可以对

AnimatedVisibility
进行任何优化吗?

任何建议或替代方法表示赞赏!

当前实施:

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun AnimatedImageWithTextItem() {
    val state = remember { mutableStateMapOf<String, Boolean>() }
    LazyColumn(
        modifier = Modifier
            .fillMaxWidth()
            .wrapContentHeight(),
    ) {
        val groupedItems = list.groupBy { it.date }
        
        groupedItems.onEachIndexed { groupIndex, (key, elements) ->
            val isExpanded = state[key] ?: true
            stickyHeader {
                Row(modifier = Modifier
                    .fillMaxWidth()
                    .height(50.dp)
                    .background(Color.Yellow)

                    .clickable { state[key] = !isExpanded })
                {
                    Text("header $key")
                }
            }

            itemsIndexed(elements) { elementIndex, element ->
                ExpandableContent(isExpanded) {
                    Row(modifier = Modifier
                        .fillMaxWidth()
                        .height(50.dp)
                        .background(Color.White)
                        .clickable { state[key] = !isExpanded })
                    {
                        Text("Item of the header")
                    }

                }
            }

        }
    }
}

const val EXPANSTION_TRANSITION_DURATION = 300
@Composable
fun ExpandableContent(
    visible: Boolean = true,
    content: @Composable () -> Unit
) {
    val enterTransition = remember {
        expandVertically(
            expandFrom = Alignment.Top,
            animationSpec = tween(EXPANSTION_TRANSITION_DURATION)
        ) + fadeIn(
            initialAlpha = 0.3f,
            animationSpec = tween(EXPANSTION_TRANSITION_DURATION)
        )
    }
    val exitTransition = remember {
        shrinkVertically(
            // Expand from the top.
            shrinkTowards = Alignment.Top,
            animationSpec = tween(EXPANSTION_TRANSITION_DURATION)
        ) + fadeOut(
            // Fade in with the initial alpha of 0.3f.
            animationSpec = tween(EXPANSTION_TRANSITION_DURATION)
        )
    }

    AnimatedVisibility(
        visible = visible,
        enter = enterTransition,
        exit = exitTransition
    ) {
        content()
    }
}

enter image description here

android android-jetpack-compose lazycolumn jetpack-compose-animation
1个回答
0
投票

您在每次重组时都调用

 val groupedItems = list.groupBy { it.date }
。这可能就是问题所在。

https://developer.android.com/develop/ui/compose/performance/bestpractices#use-remember

可组合函数可以非常频繁地运行,就像每个 动画的帧。因此,您应该尽可能少做 尽可能在可组合项的主体中进行计算。

一项重要的技术是将计算结果存储为 记住。这样,计算运行一次,您就可以获取 随时需要结果。

例如,下面是一些显示排序后的姓名列表的代码, 但排序的方式非常昂贵:

@Composable
fun ContactList(
    contacts: List<Contact>,
    comparator: Comparator<Contact>,
    modifier: Modifier = Modifier
) {
    LazyColumn(modifier) {
        // DON’T DO THIS
        items(contacts.sortedWith(comparator)) { contact ->
            // ...
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.