一、滚动进度条
<stylename="CustomProgressBar.Horizontal"parent="@android:style/Widget.ProgressBar.Horizontal"><itemname="android:indeterminateOnly">false</item><itemname="android:progressDrawable">@android:drawable/progress_horizontal</item><!-- 确定模式 --><itemname="android:indeterminateDrawable">@drawable/progress_indeterminate_horizontal</item><!-- 你的 animation-list --><itemname="minHeight">20dp</item><itemname="maxHeight">20dp</item><itemname="android:mirrorForRtl">true</item><itemname="android:padding">2dp</item></style>progress_indeterminate_horizontal文件如下:
<?xmlversion="1.0"encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot="false"><item android:drawable="@drawable/progressbar_indeterminate1"android:duration="200"/><item android:drawable="@drawable/progressbar_indeterminate2"android:duration="200"/><item android:drawable="@drawable/progressbar_indeterminate3"android:duration="200"/></animation-list>progressbar_indeterminate1、progressbar_indeterminate2、progressbar_indeterminate3分别如下:
<vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="36dp"android:height="30dp"android:viewportWidth="36"android:viewportHeight="30"><group><clip-path android:pathData="M0,0h36v30h-36z"/><path android:pathData="M0,0h36v30h-36z"android:fillColor="#CBCBCB"/><path android:pathData="M24,41L47,18"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/><path android:pathData="M-3,14L14,-3"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/><path android:pathData="M-2.5,32L33.5,-4"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/><path android:pathData="M16,32L39,9"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/></group></vector><vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="36dp"android:height="30dp"android:viewportWidth="36"android:viewportHeight="30"><group><clip-path android:pathData="M0,0h36v30h-36z"/><path android:pathData="M0,0h36v30h-36z"android:fillColor="#CBCBCB"/><path android:pathData="M14,39L42,11.5"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/><path android:pathData="M-10,11L7,-6"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/><path android:pathData="M-9,27L27,-9"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/><path android:pathData="M-1.5,37L38,-3"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/></group></vector><vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="36dp"android:height="30dp"android:viewportWidth="36"android:viewportHeight="30"><group><clip-path android:pathData="M0,0h36v30h-36z"/><path android:pathData="M0,0h36v30h-36z"android:fillColor="#CBCBCB"/><path android:pathData="M19,39L47,11.5"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/><path android:pathData="M-5,11L12,-6"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/><path android:pathData="M-3,27L33,-9"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/><path android:pathData="M4.25,37L43.75,-3"android:strokeWidth="6"android:fillColor="#00000000"android:strokeColor="#ab0b0b"/></group></vector>使用:
<ProgressBar android:id="@+id/progressBar"style="@style/CustomProgressBar.Horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:indeterminate="true"/>二、循环进度条
package com.android.simple.utils;importandroid.animation.ValueAnimator;importandroid.content.Context;importandroid.graphics.Canvas;importandroid.graphics.Color;importandroid.graphics.Paint;importandroid.graphics.RectF;importandroid.util.AttributeSet;importandroid.util.Log;importandroid.view.View;importandroid.view.animation.LinearInterpolator;public class MovingLineProgressBar extends View{private static final String TAG="MovingLineProgressBar";private float progressBarWidth=0f;// 进度条总宽度 private float lineWidth=0f;// 移动线条宽度 private float currentPosition=0f;// 当前线条位置 private Paint backgroundPaint=new Paint(Paint.ANTI_ALIAS_FLAG);private Paint linePaint=new Paint(Paint.ANTI_ALIAS_FLAG);private ValueAnimator animator;public MovingLineProgressBar(Context context){super(context);init();}public MovingLineProgressBar(Context context, AttributeSet attrs){super(context, attrs);init();}public MovingLineProgressBar(Context context, AttributeSet attrs, int defStyleAttr){super(context, attrs, defStyleAttr);init();}private voidinit(){// 初始化画笔(不变) backgroundPaint.setColor(Color.WHITE);backgroundPaint.setStyle(Paint.Style.STROKE);backgroundPaint.setStrokeWidth(8f);linePaint.setColor(Color.RED);linePaint.setStyle(Paint.Style.STROKE);linePaint.setStrokeWidth(8f);lineWidth=100f;setupAnimator();}@Override protected void onSizeChanged(int w, int h, int oldw, int oldh){super.onSizeChanged(w, h, oldw, oldh);progressBarWidth=w - lineWidth;// 注意:w 是 int,转 float // Log.d(TAG,"onSizeChanged: width = "+ w +", progressBarWidth = "+ progressBarWidth);// 如果动画已启动,但宽度变化了,重置动画if(animator!=null&&animator.isStarted()){animator.cancel();currentPosition=0f;// 重置位置 startAnimation();// 重新启动}}@Override protected void onDraw(Canvas canvas){super.onDraw(canvas);if(canvas==null)return;float centerY=getHeight()/ 2f;float left=0f;float right=getWidth();// 绘制背景进度条(不变) RectF backgroundRect=new RectF(left, centerY - 4f, right, centerY + 4f);canvas.drawRoundRect(backgroundRect, 4f, 4f, backgroundPaint);// 绘制移动线条(不变) float lineLeft=currentPosition;float lineRight=currentPosition + lineWidth;RectF lineRect=new RectF(lineLeft, centerY - 4f, lineRight, centerY + 4f);canvas.drawRoundRect(lineRect, 4f, 4f, linePaint);// Log.d(TAG,"onDraw: currentPosition = "+ currentPosition);// 调试日志}private voidsetupAnimator(){animator=ValueAnimator.ofFloat(0f, progressBarWidth);// 注意:初始时progressBarWidth=0animator.setDuration(2000L);//每轮动画持续2秒 animator.setInterpolator(new LinearInterpolator());//线性插值,确保匀速移动 animator.setRepeatCount(ValueAnimator.INFINITE);//无限重复 animator.setRepeatMode(ValueAnimator.RESTART);//每次重复从头开始(回到0位置) animator.addUpdateListener(animation ->{currentPosition=(Float)animation.getAnimatedValue();invalidate();// 可选:添加日志查看动画更新(生产环境移除) // Log.d(TAG,"Animation update: position = "+ currentPosition);});}@Override protected voidonAttachedToWindow(){super.onAttachedToWindow();// 注释掉自动启动,避免与手动启动冲突 // startAnimation();Log.d(TAG,"onAttachedToWindow: View attached");}@Override protected voidonDetachedFromWindow(){super.onDetachedFromWindow();if(animator!=null){animator.cancel();}Log.d(TAG,"onDetachedFromWindow: Animation stopped");}// 公共方法:开始动画(增强版) public voidstartAnimation(){if(animator==null){Log.e(TAG,"Animator is null, cannot start");return;}// 检查宽度是否有效if(progressBarWidth<=0){Log.w(TAG,"progressBarWidth <= 0 ("+ progressBarWidth +"), delaying start until layout");// 延迟启动,直到布局完成 post(()->{ if(progressBarWidth>0){ startAnimation();} else { Log.e(TAG,"Still invalid width after post,check layout XML");} });return;}//如果已启动,先取消 if(animator.isStarted()){animator.cancel();currentPosition=0f;// 重置位置}// 更新动画结束值(因为 ofFloat 是初始设置的) animator.setFloatValues(0f, progressBarWidth);animator.start();Log.d(TAG,"Animation started with width: "+ progressBarWidth);}public voidstopAnimation(){if(animator!=null){animator.cancel();currentPosition=0f;// 重置位置 invalidate();// 立即重绘到初始状态 Log.d(TAG,"Animation stopped");}}}使用:
binding.progressBar.startAnimation();