Реализация заказа изменения (перетаскивание) с анимацией для предметов (карт) в Lazycolumn, аналогично Applewallet?Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Реализация заказа изменения (перетаскивание) с анимацией для предметов (карт) в Lazycolumn, аналогично Applewallet?

Сообщение Anonymous »

Вот пример, как это работает в Applewallet: https://www.youtube.com/shorts/x-vcgg-wbckобразно Карта плавно движется вниз, а затем вверх < /p>
Поэтому я сделал пример примера Compose JetPack (полный код) с этой перезапорядой библиотекой (отредактировал пару строк кода), но на данный момент она использует модификатор по умолчанию по умолчанию .AnimateItem () Анимация для элементов:

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

private val CARD_HEIGHT = 500.dp

@Composable
fun ScreenContent(modifier: Modifier = Modifier) {
var items by remember { mutableStateOf((0..5).map { getRandomColor() }) }

val lazyListState = rememberLazyListState()

val cardPctHeight = 0.1f
val cardLastPctHeight = 0.5f

// https://github.com/Calvin-LL/Reorderable
val reorderableLazyListState = rememberReorderableLazyListState(
lazyListState = lazyListState,
shouldItemMoveThreshold = (CARD_HEIGHT * cardPctHeight) / 2f
) { from, to ->
items = items.toMutableList().apply {
add(to.index, removeAt(from.index))
}
}

LazyColumn(
state = lazyListState,
modifier = modifier.fillMaxSize(),
contentPadding = PaddingValues(top = 10.dp),
verticalArrangement = Arrangement.Bottom
) {
itemsIndexed(
items = items,
key = { _, item -> item.toArgb() }
) { index, item ->
ReorderableItem(reorderableLazyListState, key = item.toArgb()) {
Box(
modifier = Modifier
.padding(horizontal = 10.dp)
.draggableHandle()
.layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
val placeableHeight = if (index != items.lastIndex) {
placeable.height * cardPctHeight
} else {
placeable.height * cardLastPctHeight
}
layout(placeable.width, placeableHeight.roundToInt()) {
placeable.place(0, 0)
}
}
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
.height(CARD_HEIGHT)
.background(color = item)
) {
//
}
}
}
}
}

private fun getRandomColor(): Color {
return Color(
red = Random.nextFloat(),
green = Random.nextFloat(),
blue = Random.nextFloat(),
alpha = 1f
)
}
Прямо сейчас он работает так с анимацией по умолчанию:
https://youtube.com/shorts/gmdc6aclgrg
Эта переупорядоченная библиотека указывает анимацию по умолчанию здесь < /p>

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

@Composable
fun LazyItemScope.ReorderableItem(
...
animateItemModifier: Modifier = Modifier.animateItem(),
обновление:
Я смог получить ту же анимацию (с выходом и вводом поведения) с использованием animatedvisibility (вместо lazyitemscope.animateitem ), но он работает нормально, только если мы перетаскиваем элемент медленно, потому что есть задержки для переключения анимации (ввод/выход), а также, если мы быстрее перемещаем элемент перетаскивания. может видеть, что другие предметы подключены к их видимой высоте при их перемещении. >
code < /strong>: < /p>

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

private val CARD_HEIGHT = 500.dp

@Composable
fun AnimatedReorderableItem(
visible: Boolean,
content: @Composable () -> Unit
) {
AnimatedVisibility(
visible = visible,
enter = slideInVertically(
// The item slides in from below
initialOffsetY = { fullHeight -> fullHeight }
) + fadeIn(animationSpec = tween(durationMillis = 300)),
exit = slideOutVertically(
// The item slides out downward
targetOffsetY = { fullHeight -> fullHeight }
) + fadeOut(animationSpec = tween(durationMillis = 300))
) {
content()
}
}

@Composable
fun ScreenContent(modifier: Modifier = Modifier) {
Column {
var items by remember { mutableStateOf((0..5).map { getRandomColor() }) }

val itemVisibility = remember { mutableStateMapOf() }

val lazyListState = rememberLazyListState()

val cardPctHeight = 0.1f
val cardLastPctHeight = 0.5f

// https://github.com/Calvin-LL/Reorderable
val reorderableLazyListState = rememberReorderableLazyListState(
lazyListState = lazyListState,
shouldItemMoveThreshold = (CARD_HEIGHT * cardPctHeight) / 2f
) { from, to ->
val item = items[to.index]

itemVisibility[item] = false

// TODO: but the problem here, we can't move the dragging item too fast (before animation ends)
delay(300)

itemVisibility[item] = true

items = items.toMutableList().apply {
add(to.index, removeAt(from.index))
}
}

LazyColumn(
state = lazyListState,
modifier = modifier
.fillMaxWidth()
.weight(1f),
contentPadding = PaddingValues(top = 10.dp),
verticalArrangement = Arrangement.Bottom
) {
itemsIndexed(
items = items,
key = { _, item -> item.toArgb() }
) { index, item ->
AnimatedReorderableItem(visible = itemVisibility[item] ?: true) {
ReorderableItem(
state = reorderableLazyListState,
key = item.toArgb(),
animateItemModifier = Modifier // disable default animation Modifier.animateItem()
) {
Box(
modifier = Modifier
.padding(horizontal = 10.dp)
.longPressDraggableHandle()
.layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
val placeableHeight = if (index != items.lastIndex) {
placeable.height * cardPctHeight
} else {
placeable.height * cardLastPctHeight
}
layout(placeable.width, placeableHeight.roundToInt()) {
placeable.place(0, 0)
}
}
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
.height(CARD_HEIGHT)
.background(color = item)
) {
//
}
}
}
}
}
}
}
Как я понимаю, modifier.animateItem () ограничен и позволяет только одну анимацию перехода для размещения, мы не можем просто установить анимацию для ITEM ENTER/EXIT, как с AnimatedVisiblity .

Подробнее здесь: https://stackoverflow.com/questions/794 ... cards-in-l
Ответить

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

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

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

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

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