You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中AnimationDrawable的替代方案是什么?如何实现逐帧动画

Jetpack Compose 逐帧动画实现方案

方案1:复用原有 AnimationDrawable 实现

适合从View体系迁移、已经有成熟逐帧动画xml资源的场景,不需要修改原有资源即可快速接入。

实现步骤:

  1. 先在res/drawable目录下定义原有逐帧动画xml文件(示例名为frame_anim.xml)
  2. 用Compose提供的AndroidView组件包裹ImageView加载动画资源,示例代码如下:
AndroidView(
    factory = { context ->
        ImageView(context).apply {
            // 加载逐帧动画资源
            setImageResource(R.drawable.frame_anim)
            val animDrawable = drawable as AnimationDrawable
            // 设置是否只播放一次,false为循环播放
            animDrawable.isOneShot = false
            // 组件挂载时启动动画
            doOnAttach {
                animDrawable.start()
            }
            // 组件卸载时停止动画,避免内存泄漏
            doOnDetach {
                animDrawable.stop()
            }
        }
    },
    modifier = Modifier.size(200.dp) // 按需设置动画尺寸
)

如果需要动态构建逐帧动画,也可以直接在代码中创建AnimationDrawable实例,调用addFrame(Drawable frame, int duration)方法添加帧即可,无需提前定义xml资源。

方案2:Compose 原生声明式实现

推荐纯Compose项目使用,不依赖Android View体系,性能更优,可定制化程度更高。

实现思路是通过状态控制当前显示的帧资源,配合协程定时切换帧,示例代码如下:

@Composable
fun FrameAnimation(
    // 帧资源列表
    frameList: List<Int>,
    // 每帧停留时长,单位毫秒
    frameDuration: Int = 100,
    // 是否循环播放
    isRepeat: Boolean = true,
    modifier: Modifier = Modifier
) {
    var currentFrameIndex by remember { mutableIntStateOf(0) }
    var isPlaying by remember { mutableStateOf(true) }

    LaunchedEffect(isPlaying, currentFrameIndex) {
        if (!isPlaying) return@LaunchedEffect
        // 等待当前帧播放时长
        delay(frameDuration.toLong())
        val nextIndex = currentFrameIndex + 1
        currentFrameIndex = when {
            nextIndex < frameList.size -> nextIndex
            isRepeat -> 0
            else -> {
                // 播放到最后一帧,停止动画
                isPlaying = false
                currentFrameIndex
            }
        }
    }

    Image(
        painter = painterResource(id = frameList[currentFrameIndex]),
        contentDescription = null,
        modifier = modifier
    )
}

使用时直接传入帧资源即可:

FrameAnimation(
    frameList = listOf(R.drawable.frame1, R.drawable.frame2, R.drawable.frame3, R.drawable.frame4),
    frameDuration = 120,
    modifier = Modifier.size(200.dp)
)

该方案可以自由扩展暂停、继续、倒放、倍速、指定起始帧等自定义能力,适配更复杂的动画需求。


内容的提问来源于stack exchange,提问作者Ali Jawad Hussain Gorayya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 01:24:03