news 2026/4/23 17:41:07

Android 两种进度条(滚动进度条、循环进度条)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Android 两种进度条(滚动进度条、循环进度条)

一、滚动进度条

<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();
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:52:59

智能抠图Rembg:珠宝首饰去背景实战

智能抠图Rembg&#xff1a;珠宝首饰去背景实战 1. 引言&#xff1a;AI驱动的电商图像处理新范式 1.1 行业痛点与技术演进 在电商、广告设计和数字内容创作领域&#xff0c;高质量的产品图像处理是提升转化率的关键环节。尤其是珠宝首饰类商品&#xff0c;因其材质反光性强、…

作者头像 李华
网站建设 2026/4/23 11:50:52

信奥赛C++提高组csp-s之哈表表

信奥赛C提高组csp-s之哈表表 一、哈希表基本概念 1.1 什么是哈希表 哈希表&#xff08;Hash Table&#xff09;是一种高效的数据结构&#xff0c;它通过键值对存储数据&#xff0c;能够在平均O(1) 时间内完成插入、删除和查找操作。 1.2 核心思想 将键(key) 通过哈希函数转…

作者头像 李华
网站建设 2026/4/23 11:32:49

智能抠图Rembg:美食图片处理技巧

智能抠图Rembg&#xff1a;美食图片处理技巧 1. 引言&#xff1a;智能万能抠图 - Rembg 在电商、社交媒体和内容创作领域&#xff0c;高质量的图像去背景需求日益增长。尤其是美食图片处理&#xff0c;往往需要将诱人的食物从杂乱背景中精准分离&#xff0c;用于菜单设计、广…

作者头像 李华
网站建设 2026/4/18 0:41:48

Rembg模型解释:显著性目标检测原理

Rembg模型解释&#xff1a;显著性目标检测原理 1. 智能万能抠图 - Rembg 在图像处理与内容创作领域&#xff0c;自动去背景是一项高频且关键的需求。无论是电商商品图精修、社交媒体头像设计&#xff0c;还是AI绘画素材准备&#xff0c;传统手动抠图耗时耗力&#xff0c;而通…

作者头像 李华
网站建设 2026/4/23 11:37:18

浅谈如何设计自动化测试框架

关于测试框架的好处&#xff0c;比如快速回归提高测试效率&#xff0c;提高测试覆盖率等这里就不讨论了。这里主要讨论自动化框架包含哪些内容&#xff0c;以及如何去设计一个测试框架。 1. 什么是自动化测试框架&#xff1f; 它是由一个或多个自动化测试基础模块、自动化测试…

作者头像 李华