Анимация элементов композиции после фильтрации и настройки новых элементов.Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Анимация элементов композиции после фильтрации и настройки новых элементов.

Сообщение Anonymous »

Я анимирую элементы, когда они входят в композицию внутри FlowRow, это также происходит и в LazyColumn/Row, Column. Когда пользователь фильтрует, получает данные из списка по умолчанию и отображает элементы на основе некоторых критериев фильтра. Однако некоторые элементы не покидают композицию и не входят в нее, поэтому их LaunchedEffect(Unit) никогда не вызывается.
Я пытался изменить данные, чтобы они были нестабильными, переопределение равно возврату false, использование копии для передачи новых ссылок, обновление некоторого идентификатора для проверки отображения старых данных, использование SnapshotStateList, как в фактической реализации, с очисткой и добавлением элементов, но даже с новыми данными Composable не удаляются, и потому что из них не компонуются и не анимируются после фильтрации.
Изображение

Код: Выделить всё

@Preview
@Composable
fun Test() {
val viewModel = viewModel()
MyComposable(viewModel)
}

@Composable
fun MyComposable(someViewModel: SomeViewModel) {

Column {

Button(
modifier = Modifier.padding(16.dp).fillMaxWidth(),
onClick = {
someViewModel.filter()
}
) {
Text("Filter")
}

val itemList = someViewModel.itemList

BoxWithConstraints(
modifier = Modifier.padding(horizontal = 16.dp)
) {

val itemWidth = (maxWidth - 8.dp) / 2

FlowRow(
modifier = Modifier.fillMaxSize(),
maxItemsInEachRow = 2,
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {

itemList.forEach {
key(it.id) {
MyRow(
modifier = Modifier.size(itemWidth),
item = it
)
}
}

}
}
}
}

@Composable
fun MyRow(
modifier: Modifier = Modifier,
item: SomeData,
) {

var visible by remember {
mutableStateOf(false)
}

var counter by remember {
mutableIntStateOf(0)
}

LaunchedEffect(Unit) {
println("Composing $item")
visible = true
}

val context = LocalContext.current

DisposableEffect(Unit) {
onDispose {
Toast.makeText(context, "Item ${item.id} is leaving composition", Toast.LENGTH_SHORT).show()
}
}

AnimatedVisibility(
visible = visible,
enter = fadeIn(
tween(300)
) + scaleIn(
tween(300)
)
) {
Column(
modifier = modifier
.shadow(2.dp, RoundedCornerShape(16.dp))
.background(Color.White, RoundedCornerShape(16.dp))
.padding(16.dp)
) {
Text("id: ${item.id}, value: ${item.value}")
Spacer(modifier = Modifier.weight(1f))
Button(
modifier = Modifier.fillMaxWidth(),
onClick = {
counter++
}
) {
Text("Counter: $counter")
}
}
}
}

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)

private var counter: Int = 0

fun filter() {
if (counter % 3 == 0) {
itemList = listOf(
list[0],
list[1],
list[2]
)
} else if (counter % 3 == 1) {
itemList = listOf(
list[1],
list[2]
)
} else {
itemList = listOf(
list[2],
list[3]
)
}

counter++
}
}

data class SomeData(val id: String, val value:  String)
Еще один образец с уникальным идентификатором и функцией копирования для передачи новых ссылок.
[img]https: //i.sstatic.net/jtL0jgeF.gif[/img]

Код: Выделить всё

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)

private var counter: Int = 0

fun filter() {
if (counter % 3 == 0) {
itemList = listOf(
list[0].copy(uniqueId = UUID.randomUUID().toString()),
list[1].copy(uniqueId = UUID.randomUUID().toString()),
list[2].copy(uniqueId = UUID.randomUUID().toString())
)
} else if (counter % 3 == 1) {
itemList = listOf(
list[1].copy(uniqueId = UUID.randomUUID().toString()),
list[2].copy(uniqueId = UUID.randomUUID().toString())
)
} else {
itemList = listOf(
list[2].copy(uniqueId = UUID.randomUUID().toString()),
list[3].copy(uniqueId = UUID.randomUUID().toString())
)
}

counter++
}
}

data class SomeData(val id: String, val value: String, var uniqueId:String = "")
Изменить
Я решил эту проблему, используя uniqueKey в качестве ключа

Код: Выделить всё

itemList.forEach {
key(it.uniqueKey) {
MyRow(
modifier = Modifier.size(itemWidth),
item = it
)
}
}
для воспроизведения проблемы можно заставить элементы выходить и входить в состав, если ключи не совпадают с предыдущими значениями ни в одном индексе, но я ищу способ решить эту проблему без класса данных с изменяемыми параметрами и определенно без какой-либо связи между Composable содержит FlowRow и ViewModel. В реальной реализации FlowRow получает только элементы, фильтрация осуществляется через другой Composable.
Возможно, элементы будут входить в композицию или выходить из нее, используя данные с некоторой проверкой различий, например AnimatedContent или AnimataeVisibility имеет отдельные состояния.

Подробнее здесь: https://stackoverflow.com/questions/791 ... -new-items
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»