RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1598012
Accepted
Sirop4ik
Sirop4ik
Asked:2024-10-28 04:37:23 +0000 UTC2024-10-28 04:37:23 +0000 UTC 2024-10-28 04:37:23 +0000 UTC

如何使 LazyGrid 上某个项目的动画仅在第一次发生?

  • 772

这应该不会太困难,但由于某种原因,重组经历了两次,这使得添加仅第一次执行动画的条件变得困难。

一般来说,我想像这个例子那样做,但我改变了一点,但本质是一样的 - https://yasincamaz.medium.com/simple-item-animation-with-jetpack-composes-lazygrid -78316992af22

网格元素出现气泡效果是必要的

这是代码

private val dataSet: List<String> = listOf("Item 1", "Item 2", "Item 3", "Item 4", "Item 5")
private val data: List<String> = 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<String>
) {
    val config: List<String> = 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<Float>
): Pair<Float, Float> {
    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<Float, Float> = { idx, columns ->
    scaleAndAlpha(
        args = ScaleAndAlphaArgs(2f, 1f, 0f, 1f),
        animation = tween(300, delayMillis = (idx / columns) * 100)
    )
}

您可以尝试将Gallery其更改为此以跟踪该元素是否已向用户显示

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

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

    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 ->因此,该元素出现在屏幕上就好像没有动画一样

我在这里缺少什么?

android
  • 1 1 个回答
  • 23 Views

1 个回答

  • Voted
  1. Best Answer
    Sirop4ik
    2024-10-28T20:28:14Z2024-10-28T20:28:14Z

    在第一次重组项目 lambda 时,当 shouldAnimate 为 true 时,将调用scaleAndAlpha。这是一个 Compose 函数,它会在动画的每一帧上重新编译,并在每次重新组合时返回当前的比例和 alpha 值。为了确保 MyItem 相应更新,当比例和 alpha 更改时,会重新编译整个项目 lambda。

    第二次重组是不可取的,因为 shouldAnimate 现在设置为 false 并且刚刚开始的动画被完全跳过。

    一个简单的解决方案是将scaleAndAlpha 和MyItem 移动到一个单独的可组合元素中,以便其重新组合不依赖于shouldAnimate。

        @Composable
        private fun MyAnimatedItem(
            shouldAnimate: Boolean,
            idx: Int,
            columns: Int,
            item: String,
        ) {
            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,
            )
        }
    
    Simply called like this (in addition I simplified it to use `itemsIndexed` instead of  `items`):
    
        itemsIndexed(config) { idx, item ->
            // Determine if the item should animate
            val shouldAnimate = !animatedIndices.contains(idx)
    
            // If it should animate, mark it as animated
            if (shouldAnimate) {
                animatedIndices.add(idx)
            }
    
            MyAnimatedItem(shouldAnimate, idx, columns, item)
        }
    

    现在,由于动画而发生的重组受到限制MyAnimatedItem,lambdaitemsIndexed不受影响,并且仅在元素滚动到范围之外并返回时才重新编译。只有这样,shouldAnimate它才会false按照预期安装在 中。

    • 0

相关问题

  • 来自片段的列表落后于 BottomNavigationView

  • 无法将变量从 Activity 传递到 Fragment

  • 构建与完成的片段略有不同的片段的最佳方法是什么?

  • 如何更改来自服务器的响应中的日期格式?

  • 谷歌地图在应用程序的发布版本中不起作用

  • 材料设计按钮。单击按钮上的可选区域!

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5