Как заставить анимацию в Lazy Grid для элемента выполняться только при первом появлении?Android

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Как заставить анимацию в Lazy Grid для элемента выполняться только при первом появлении?

Сообщение Anonymous »

По какой-то причине происходит 2 перекомпостирования, в результате чего невозможно установить условие для проверки элемента, был ли он уже представлен пользователю.
Я хотел бы сделать вот такая анимация для LazyGrid (пытался немного оптимизировать свой код, но смысл тот же) - https://yasinkacmaz.medium.com/simple-i ... 316992af22
Создание эффекта пузыря
Вот мой код:

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

private val dataSet: List = listOf("Item 1", "Item 2", "Item 3", "Item 4", "Item 5")
private val data: List = List(5) { dataSet }.flatten()

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
Test_delete_itTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Gallery(
paddingValues = innerPadding,
uiConfig = { data }
)
}
}
}
}
}

@Composable
private fun Gallery(
paddingValues: PaddingValues,
uiConfig: () -> List
) {
val config: List = uiConfig()
val columns = 2

Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
LazyVerticalGrid(
columns = GridCells.Fixed(columns),
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
content = {
items(config.size) { idx ->
val item: String = config[idx]
val (scale, alpha) = scaleAndAlpha(idx, columns)

MyItem(
modifier = Modifier.graphicsLayer(alpha = alpha, scaleX = scale, scaleY = scale),
text = item
)
}
}
)
}
}

@Composable
private fun MyItem(
modifier: Modifier = Modifier,
text: String
) {
Card(
modifier = modifier.height(150.dp),
shape = RoundedCornerShape(16.dp),
elevation = CardDefaults.cardElevation(8.dp),
colors = CardDefaults.cardColors(
containerColor = Color.Blue,
)
) {
Box(
modifier = Modifier
.weight(1f)
.height(150.dp)
.clip(RoundedCornerShape(16.dp))
) {
Text(
text = text,
color = Color.White
)
}
}
}

@Immutable
private enum class State { PLACING, PLACED }

@Immutable
data class ScaleAndAlphaArgs(
val fromScale: Float,
val toScale: Float,
val fromAlpha: Float,
val toAlpha: Float
)

@OptIn(ExperimentalTransitionApi::class)
@Composable
fun scaleAndAlpha(
args: ScaleAndAlphaArgs,
animation: FiniteAnimationSpec
): Pair {
val transitionState = remember { MutableTransitionState(State.PLACING).apply { targetState = State.PLACED } }
val transition = rememberTransition(transitionState, label = "")
val alpha by transition.animateFloat(transitionSpec = { animation }, label = "") {
if (it == State.PLACING) args.fromAlpha else args.toAlpha
}
val scale by transition.animateFloat(transitionSpec = { animation }, label = "") {
if (it == State.PLACING) args.fromScale else args.toScale
}
return alpha to scale
}

val scaleAndAlpha: @Composable (idx: Int, columns: Int) -> Pair = { idx, columns ->
scaleAndAlpha(
args = ScaleAndAlphaArgs(2f, 1f, 0f, 1f),
animation = tween(300, delayMillis = (idx / columns) * 100)
)
}
Я попробовал добавить условие, представленное впервые:

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

@Composable
private fun Gallery(
paddingValues: PaddingValues,
uiConfig: () -> List
) {
val config: List  = uiConfig()
val columns = 2

// Remember a set of already animated indices
val animatedIndices = remember { mutableSetOf() }

Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
LazyVerticalGrid(
columns = GridCells.Fixed(columns),
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
content = {
items(config.size) { idx ->
val item: String = config[idx]

// Determine if the item should animate
val shouldAnimate = !animatedIndices.contains(idx)

// If it should animate, mark it as animated
if (shouldAnimate) {
animatedIndices.add(idx)
}

val (scale, alpha) = if (shouldAnimate) {
scaleAndAlpha(idx, columns)
} else {
1f to 1f // No animation
}

MyItem(
modifier = Modifier.graphicsLayer(alpha = alpha, scaleX = scale, scaleY = scale),
text = item
)
}
}
)
}
}
Но проблема в том, что рекомпозиция здесь происходит дважды — items(config.size) { idx ->, что делает условие бесполезным.
Что мне здесь не хватает?

Подробнее здесь: https://stackoverflow.com/questions/791 ... appearence
Реклама
Ответить Пред. темаСлед. тема

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

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

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

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

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

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