android:repeatCount="infinite"在set中无效

Android动画重复机制
本文探讨了如何在Android中实现无限循环的闪烁效果动画,并详细解释了使用AnimationListener监听器进行动画控制的方法。此外,还对比了不同设置下动画的表现差异。

xml如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:repeatCount="infinite"
    android:repeatMode="restart">  
    <alpha  
        android:fromAlpha="0.0"  
        android:toAlpha="1.0"  
        android:duration="1000"/>  
    <alpha
        android:startOffset="3000"
        android:fromAlpha="1.0"  
        android:toAlpha="0.0"  
        android:duration="1000"/>
</set>

本来想实现的功能是让透明度从0 到1, 等待2秒,再让透明度从1到0, 以达到闪烁的目的; 这样做的好处是可以控制显示的时间;


有人说在代码中设置setRepeatCount(Animation.INFINITE);就可以了, 实际测试下来还是不行,最好是通过设置AnimationListener, 在onAnimationEnd事件中再次开始动画来完成“repeat”的。

Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing);
            anim.setAnimationListener(new AnimationListener() {

                @Override
                public void onAnimationEnd(Animation arg0) {
                    Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing);
                    anim.setAnimationListener(this);
                    brackets.startAnimation(anim);

                }

                @Override
                public void onAnimationRepeat(Animation arg0) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onAnimationStart(Animation arg0) {
                    // TODO Auto-generated method stub

                }

            });


-------------------------------------------------------------------------------------------------------------------------------------

题外话:

虽然只用alpha动画, 设置如下也可以实现闪烁的效果,但是不太好控制显示时间。如果想让渐变的时间不一致就更没辙了。

alpha.setRepeatCount(Animation.INFINITE);

alpha.setRepeatMode(Animation.REVERSE);

-------------------------------------------------------------------------------------------------------------------------------------


讨论帖:http://stackoverflow.com/questions/4480652/android-animation-does-not-repeat

是的,你可以使用这个 **`<rotate>` 动画** 来实现 Loading 图标的旋转效果,但需要注意以下几点: --- ## **1. 你的 XML 是有效的,但需要调整** 你的代码是一个 **`RotateDrawable`**(旋转动画),但它不是 `AnimatedVectorDrawable` 或 `AnimationDrawable`,而是 **`<rotate>` 标签定义的位图旋转动画**。 ### **修改后的 `rotate_loading.xml`(推荐)** ```xml <?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/your_loading_icon" <!-- 替换为你的图片资源 --> android:duration="1000" <!-- 每次旋转的持续时间(毫秒) --> android:fromDegrees="0" <!-- 起始角度 --> android:toDegrees="360" <!-- 结束角度(360° 表示完整旋转) --> android:pivotX="50%" <!-- 旋转中心点 X(50% 表示图片中心) --> android:pivotY="50%" <!-- 旋转中心点 Y --> android:repeatCount="infinite" <!-- 无限循环 --> /> ``` ### **关键点** - **`android:toDegrees="360"`**(而不是 `359`)确保完整旋转一圈。 - **`android:repeatCount="infinite"`**(而不是 `-1`)更符合规范(两者效果相同)。 - **`android:drawable`** 应指向你的 Loading 图标(如 `@drawable/ic_loading`),而不是 `@mipmap/`(`mipmap` 通常用于启动图标)。 --- ## **2. 如何在 `SpannableStringBuilder` 中使用?** 由于 `RotateDrawable` 不是 `Animatable`(不能直接调用 `start()`),你需要: 1. **用 `LayerDrawable` 包装 `RotateDrawable`**,使其支持动画。 2. **或者改用 `AnimationDrawable` 或 `AnimatedVectorDrawable`**(推荐)。 ### **方法 1:改用 `AnimationDrawable`(兼容性更好)** ```xml <!-- res/drawable/loading_frames.xml --> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/frame1" android:duration="100" /> <item android:drawable="@drawable/frame2" android:duration="100" /> <item android:drawable="@drawable/frame3" android:duration="100" /> </animation-list> ``` 然后按 **方法 2** 的代码使用 `AnimationDrawable`。 ### **方法 2:用 `LayerDrawable` 包装 `RotateDrawable`(不推荐)** ```kotlin val rotateDrawable = ContextCompat.getDrawable(context, R.drawable.rotate_loading) val layerDrawable = LayerDrawable(arrayOf(rotateDrawable)) layerDrawable.setBounds(0, 0, 50, 50) val imageSpan = ImageSpan(layerDrawable, ImageSpan.ALIGN_BASELINE) val spannable = SpannableStringBuilder("加载中").apply { append(" ") setSpan(imageSpan, length - 1, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) } textView.text = spannable // 手动启动动画(需要额外处理) rotateDrawable?.let { val anim = AnimationUtils.loadAnimation(context, R.anim.rotate_anim) // 定义一个 <rotate> 动画 it.startAnimation(anim) } ``` **问题**:`RotateDrawable` 不能直接用于 `ImageSpan`,需要额外处理动画逻辑。 --- ## **3. 推荐方案** ### **✅ 最佳选择:改用 `AnimatedVectorDrawable`** ```xml <!-- res/drawable/avd_loading.xml --> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_loading"> <!-- 静态矢量图 --> <target android:name="rotation" android:animation="@anim/rotate" /> </animated-vector> ``` ```xml <!-- res/anim/rotate.xml --> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:propertyName="rotation" android:repeatCount="infinite" android:valueFrom="0" android:valueTo="360" /> ``` 然后按 **方法 1** 的代码使用 `AnimatedVectorDrawable`。 --- ## **4. 总结** | 方案 | 适用场景 | 是否推荐 | |------|---------|---------| | **`<rotate>` + `RotateDrawable`** | 简单旋转位图 | ❌ 不推荐(无法直接用于 `ImageSpan`) | | **`AnimationDrawable`** | 帧动画 | ✅ 推荐(兼容性好) | | **`AnimatedVectorDrawable`** | 矢量动画 | ✅✅ 最佳(流畅、省内存) | | **外部 `ProgressBar`** | 复杂动画 | ⚠️ 可选(灵活性高) | ### **最终建议** - **如果只是简单旋转** → 改用 `AnimationDrawable` 或 `AnimatedVectorDrawable`。 - **如果坚持用 `<rotate>`** → 建议改用 `ProgressBar` 或 `Lottie` 动画。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值