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

如何为ImageView添加波纹动画?加载图片前展示动画失败

解决ImageView加载前的波纹动画问题

原代码的问题

  • RippleDrawable是为触摸交互设计的组件,不会自动播放波纹效果,必须触发触摸事件才会产生波纹
  • AnimationDrawable仅添加了单个帧,没有帧序列的变化逻辑,无法形成可见的动画效果

方案一:用ObjectAnimator实现自动波纹扩散动画

通过缩放+透明度的组合动画,模拟无限循环的波纹扩散效果,无需依赖触摸事件。

步骤1:创建波纹形状Drawable

在res/drawable目录下新建ripple_loading.xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#80000000"/> <!-- 半透明黑色,可根据需求调整颜色 -->
</shape>

步骤2:调整布局结构

给ImageView添加一个覆盖层View作为动画载体,避免动画影响图片显示:

<FrameLayout
    android:layout_width="100dp"
    android:layout_height="100dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <View
        android:id="@+id/ripple_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/ripple_loading"/>
</FrameLayout>

步骤3:实现动画逻辑

在代码中配置并启动无限循环动画,图片加载完成后停止并隐藏动画:

ImageView imageView = findViewById(R.id.image_view);
View rippleView = findViewById(R.id.ripple_view);

// 创建缩放动画:从0.2倍放大到1.5倍
ObjectAnimator scaleX = ObjectAnimator.ofFloat(rippleView, "scaleX", 0.2f, 1.5f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(rippleView, "scaleY", 0.2f, 1.5f);
// 创建透明度动画:从完全显示到完全透明
ObjectAnimator alpha = ObjectAnimator.ofFloat(rippleView, "alpha", 1f, 0f);

// 组合动画,设置时长与循环规则
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(scaleX, scaleY, alpha);
animatorSet.setDuration(1500);
animatorSet.setRepeatCount(ValueAnimator.INFINITE);
animatorSet.setRepeatMode(ValueAnimator.RESTART);

animatorSet.start();

// 示例:用Glide加载图片,完成后停止动画
Glide.with(this)
     .load("你的服务器图片URL")
     .into(new CustomTarget<Drawable>() {
         @Override
         public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
             imageView.setImageDrawable(resource);
             animatorSet.cancel();
             rippleView.setVisibility(View.GONE);
         }

         @Override
         public void onLoadCleared(@Nullable Drawable placeholder) {}
     });

方案二:用AnimationDrawable实现帧动画

如果必须使用AnimationDrawable,需要准备多帧递进的波纹Drawable:

步骤1:创建帧动画配置文件

在res/anim目录下新建ripple_frames.xml:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="@drawable/ripple_frame1" android:duration="300"/>
    <item android:drawable="@drawable/ripple_frame2" android:duration="300"/>
    <item android:drawable="@drawable/ripple_frame3" android:duration="300"/>
    <item android:drawable="@drawable/ripple_frame4" android:duration="300"/>
</animation-list>

其中ripple_frame1到ripple_frame4是依次增大、透明度逐渐降低的圆形Drawable。

步骤2:启动帧动画

ImageView imageView = findViewById(R.id.image_view);
imageView.setBackgroundResource(R.anim.ripple_frames);
AnimationDrawable anim = (AnimationDrawable) imageView.getBackground();
anim.start();

// 图片加载完成后停止并清理动画
// anim.stop();
// imageView.setBackground(null);
// imageView.setImageDrawable(加载的图片);

关键注意事项

  • 不要用RippleDrawable实现自动播放动画,它的核心定位是触摸反馈
  • 图片加载完成后必须停止动画并清理资源,避免内存泄漏
  • 若使用第三方图片加载库,可结合其占位图机制简化逻辑,但自定义动画灵活性更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 16:55:24