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

AnimatedVectorDrawableCompat循环动画API21-24无法重复问题咨询

解决AnimatedVectorDrawableCompat在API21-24上仅播放一次的循环问题

我来帮你搞定这个兼容性问题,先分析下原因,再给几个非hack的可靠方案:

问题原因

这是旧版本AnimatedVectorDrawableCompat在API21-24上的已知实现缺陷:当动画结束触发onAnimationEnd回调时,内部的动画状态还没完全重置完成,此时直接调用start()虽然会执行方法,但无法正确重启动画。而API25+的系统和Compat库修复了这个状态同步的问题,所以表现正常。

非hack解决方案

方案1:延迟重启动画(最简单的修复)

利用View的post()方法,把重启动画的操作放到下一次UI消息循环中,让系统有足够时间完成动画状态的重置:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    imageView = findViewById(R.id.image_view1);
    final AnimatedVectorDrawableCompat anim = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_pass_inside);
    imageView.setImageDrawable(anim);
    
    anim.registerAnimationCallback(new Animatable2Compat.AnimationCallback() {
        @Override
        public void onAnimationEnd(Drawable drawable) {
            // 用post把重启操作放到UI线程的消息队列末尾
            imageView.post(() -> {
                if (anim.isRunning()) {
                    anim.stop();
                }
                anim.start();
            });
        }
    });
    anim.start();
}

方案2:用ValueAnimator手动控制循环(最稳定的方案)

直接绕过AnimatedVectorDrawable的自动循环,用ValueAnimator来驱动动画进度,这种方式在所有API版本上表现一致:

private AnimatedVectorDrawableCompat anim;
private ValueAnimator loopAnimator;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    imageView = findViewById(R.id.image_view1);
    anim = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_pass_inside);
    imageView.setImageDrawable(anim);

    // 创建循环动画控制器
    loopAnimator = ValueAnimator.ofFloat(0f, 1f);
    // 获取AVD的默认时长作为动画周期
    loopAnimator.setDuration(anim.getIntrinsicDuration());
    // 设置无限循环
    loopAnimator.setRepeatCount(ValueAnimator.INFINITE);
    loopAnimator.addUpdateListener(animation -> {
        float progress = (float) animation.getAnimatedValue();
        anim.setProgress(progress);
    });
    
    loopAnimator.start();
}

// 记得在生命周期里管理动画,避免内存泄漏
@Override
protected void onPause() {
    super.onPause();
    if (loopAnimator != null && loopAnimator.isRunning()) {
        loopAnimator.pause();
    }
}

@Override
protected void onResume() {
    super.onResume();
    if (loopAnimator != null && loopAnimator.isPaused()) {
        loopAnimator.resume();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (loopAnimator != null) {
        loopAnimator.cancel();
        loopAnimator = null;
    }
}

方案3:升级AppCompat库版本

如果你的项目使用的AppCompat版本比较旧,升级到1.3.0及以上版本可能已经修复了这个兼容性bug:

在你的build.gradle(Module级别)中更新依赖:

implementation 'androidx.appcompat:appcompat:1.6.1'

额外注意事项

  • 记得在Activity的生命周期方法(onPause/onResume/onDestroy)中管理动画的状态,避免后台耗电或内存泄漏;
  • 不要在非UI线程操作动画,虽然你提到动画运行在非UI线程不阻塞界面,但AnimatedVectorDrawable的状态更新最好还是在UI线程进行,避免潜在的状态异常。

内容的提问来源于stack exchange,提问作者tplive

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:34:18