Jetpack Compose中AnimatedVisibility淡入动画对重组项失效问题
需求与问题
我需要基于用户选择对LazyColumn内部FlowRow中的项进行筛选,并添加动画效果。为避免滚动位置跳动,要求项不被移出组合,但之前筛选中已存在于组合内的项不会触发AnimatedVisibility的fadeIn动画,收缩、展开、滑动等其他动画需正常工作。
从演示动图可见:首次筛选时item1、第二次筛选时item3均未执行淡入动画。
ViewModel及筛选逻辑(部分代码省略)
class SomeViewModel : ViewModel() { private val list = listOf( SomeData(id = "1", value = "Row1"), SomeData(id = "2", value = "Row2"), SomeData(id = "3", value = "Row3"), SomeData(id = "4", value = "Row4"), SomeData(id = "5", value = "Row5") ) var itemList by mutableStateOf(list) var filter: Int = 0 fun filter() { if (filter % 3 == 0) { itemList = listOf( list[0], list[1], list[2] ) } else if (filter % 3 == 1) { itemList = listOf( list[1], list[2] ) } else { itemList = listOf( list[0], list[2], list[3] ) } filter++ } } data class SomeData(val id: String, val value: String)
包含动画逻辑的Composable
@Composable private fun StaggeredList( filter: String, itemList: List<SomeData>, ) { BoxWithConstraints( modifier = Modifier ) { val itemWidth = (maxWidth - 8.dp) / 2 FlowRow( modifier = Modifier, maxItemsInEachRow = 2, horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { itemList.forEachIndexed { index, it -> key(it.id) { var visible by remember { mutableStateOf(false) } LaunchedEffect(filter) { visible = false delay(2000) visible = true } AnimatedVisibility( visible = visible, enter = fadeIn(tween(2000)), exit = fadeOut(tween(2000)) ) { MyRow( modifier = Modifier.size(itemWidth, 200.dp), item = it ) } } } } } }
(注:原代码中itemList.forEachIndexed { index, it -为笔误,已修正为->)
其余复现代码
@Preview @Composable private fun FlowRowCompositionPreview() { val viewModel = viewModel<SomeViewModel>() MyComposable(viewModel) } @Composable fun MyComposable(someViewModel: SomeViewModel) { Column(modifier = Modifier.fillMaxSize().background(backgroundColor)) { val itemList = someViewModel.itemList LazyColumn( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(8.dp), contentPadding = PaddingValues(16.dp) ) { items(5) { Box( modifier = Modifier .background(Color.Red, RoundedCornerShape(16.dp)) .fillMaxWidth().height(100.dp) ) } item { Button( modifier = Modifier.padding(16.dp).fillMaxWidth(), onClick = { someViewModel.filter() } ) { Text("Filter") } } item { StaggeredList( filter = someViewModel.filter.toString(), itemList = itemList ) } } } }
内容的提问来源于stack exchange,提问作者Thracian
相关产品推荐
相关产品推荐

