如何使用Java调整Android中ProgressBar的旋转速度
解决方案
你当前XML布局中android:indeterminate="false"为确定进度模式,该模式不会自动无限旋转,要实现无限循环效果请先将该属性改为true,或在Java代码中动态调用setIndeterminate(true)开启。
原生AppCompat圆形ProgressBar未提供公开API直接调整旋转速度,旋转动画封装在内部的IndeterminateDrawable中,可通过以下两种Java代码方案调整转速:传入的时长参数越大,旋转速度越慢。
方案1:反射修改原有动画时长(代码量少,兼容绝大多数场景)
直接拿到控件内部的旋转动画实例,修改动画时长即可生效,封装好的工具方法如下:
import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.os.Build; import android.view.animation.Animation; import android.widget.ProgressBar; import java.lang.reflect.Field; public class ProgressBarSpeedUtils { /** * 调整无限循环ProgressBar的旋转速度 * @param progressBar 目标控件实例 * @param rotateDurationMs 旋转一圈的时长,单位毫秒,默认系统值约1500ms */ public static void setRotateSpeed(ProgressBar progressBar, long rotateDurationMs) { progressBar.setIndeterminate(true); Drawable indeterminateDrawable = progressBar.getIndeterminateDrawable(); if (indeterminateDrawable == null) return; try { // 拿到内层实际持有动画的Drawable对象 Field innerDrawableField = indeterminateDrawable.getClass().getDeclaredField("mDrawable"); innerDrawableField.setAccessible(true); Object innerDrawable = innerDrawableField.get(indeterminateDrawable); if (innerDrawable == null) return; // 兼容不同SDK版本的动画字段名 Field animField; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { animField = innerDrawable.getClass().getDeclaredField("mAnimation"); } else { animField = innerDrawable.getClass().getDeclaredField("mRotateAnimation"); } animField.setAccessible(true); Animation rotateAnim = (Animation) animField.get(innerDrawable); if (rotateAnim != null) { rotateAnim.setDuration(rotateDurationMs); // 重置动画让新时长生效 indeterminateDrawable.setVisible(false, false); indeterminateDrawable.setVisible(true, false); if (indeterminateDrawable instanceof Animatable) { ((Animatable) indeterminateDrawable).start(); } } } catch (Exception e) { e.printStackTrace(); } } }
调用方式
在页面初始化拿到ProgressBar实例后直接调用即可,比如设置为3秒转一圈(比默认速度慢一半):
ProgressBar progressBar = findViewById(R.id.progressBar); // 数值越大旋转越慢,可根据需求调整 ProgressBarSpeedUtils.setRotateSpeed(progressBar, 3000);
方案2:自定义旋转Drawable(无反射,稳定性最高)
如果担心反射在个别版本存在兼容性问题,可以直接在Java代码中创建自定义旋转Drawable,自行控制动画时长后设置给ProgressBar,示例代码如下:
import android.animation.ObjectAnimator; import android.graphics.drawable.Drawable; import android.graphics.drawable.RotateDrawable; import android.view.animation.LinearInterpolator; import android.widget.ProgressBar; // 拿到系统默认的ProgressBar圆形Drawable ProgressBar progressBar = findViewById(R.id.progressBar); Drawable defaultDrawable = progressBar.getIndeterminateDrawable(); RotateDrawable rotateDrawable = new RotateDrawable(); rotateDrawable.setDrawable(defaultDrawable); // 设置从0到360度旋转 rotateDrawable.setFromDegrees(0f); rotateDrawable.setToDegrees(360f); rotateDrawable.setPivotX(0.5f); rotateDrawable.setPivotY(0.5f); // 给ProgressBar设置自定义Drawable progressBar.setIndeterminateDrawable(rotateDrawable); progressBar.setIndeterminate(true); // 通过属性动画控制旋转,时长自定义 ObjectAnimator animator = ObjectAnimator.ofInt(rotateDrawable, "level", 0, 10000); animator.setDuration(3000); // 3秒转一圈,数值越大越慢 animator.setInterpolator(new LinearInterpolator()); animator.setRepeatCount(ObjectAnimator.INFINITE); animator.start();
参数参考
- 系统默认旋转一圈时长约1500ms,对应常规速度
- 传入3000ms时,旋转速度为默认的1/2
- 传入4500ms时,旋转速度为默认的1/3
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

