当前位置: 首页 > news >正文

PrgogressBar实现原理分析

ProgressBar 是 Android 中用于显示进度条的控件,它可以用来表示任务的完成程度或者加载进度等信息。ProgressBar 有两种主要类型:一种是确定性的(determinate),另一种是不确定性的(indeterminate)。确定性进度条有一个明确的最大值,而不确定性进度条则通常用来表示正在进行的任务,没有明确的结束时间。

下面我们将结合源码来分析 ProgressBar 的实现原理。

1. ProgressBar 类定义

ProgressBar 是一个自定义的 View,它继承自 View 并实现了 Drawable.Callback 接口。

1public class ProgressBar extends View implements Drawable.Callback {
2    // ...
3}

2. 构造函数

ProgressBar 的构造函数接受 ContextAttributeSetint 类型的默认样式参数。

1public ProgressBar(Context context) {
2    this(context, null);
3}
4
5public ProgressBar(Context context, AttributeSet attrs) {
6    this(context, attrs, android.R.attr.progressBarStyle);
7}
8
9public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
10    super(context, attrs, defStyleAttr);
11    init(context, attrs, defStyleAttr, 0);
12}

3. 初始化

init 方法用于初始化 ProgressBar 的样式和行为。

1private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
2    // ...
3    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProgressBar, defStyleAttr, defStyleRes);
4    // ...
5    // 读取样式属性
6    mMax = a.getInt(R.styleable.ProgressBar_max, 100);
7    mProgress = a.getInt(R.styleable.ProgressBar_progress, 0);
8    // ...
9    a.recycle();
10    // 初始化绘制器
11    mIndeterminateProgressDrawable = new IndeterminateProgressDrawable(context, this, a);
12    mProgressDrawable = new ProgressDrawable(context, this, a);
13    // 设置默认的绘制器
14    setProgressDrawable(mProgressDrawable);
15    // ...
16}

4. 设置样式

ProgressBar 支持通过 XML 属性来设置样式。

1<ProgressBar
2    android:id="@+id/progress_bar"
3    android:layout_width="wrap_content"
4    android:layout_height="wrap_content"
5    android:indeterminate="true"  // 不确定性进度条
6    android:max="100"             // 最大值
7    android:progress="50"         // 当前进度
8    android:secondaryProgress="80" // 第二进度
9    android:background="#FF0000"  // 背景颜色
10    android:progressDrawable="@drawable/custom_progress_drawable" />

5. 设置进度

ProgressBar 提供了 setProgress 方法来设置进度条的当前进度。

1public void setProgress(int progress, boolean fromUser) {
2    if (progress != mProgress) {
3        mProgress = progress;
4        invalidate();  // 重新绘制进度条
5    }
6}

6. 设置最大值

setMax 方法用于设置进度条的最大值。

1public void setMax(int max) {
2    if (max != mMax) {
3        mMax = max;
4        invalidate();  // 重新绘制进度条
5    }
6}

7. 绘制进度条

ProgressBar 重写了 onDraw 方法来绘制进度条。

1@Override
2protected synchronized void onDraw(Canvas canvas) {
3    // ...
4    // 绘制进度条
5    if (mProgressDrawable != null) {
6        mProgressDrawable.draw(canvas);
7    }
8    // ...
9}

8. 绘制器

ProgressBar 使用 Drawable 对象来绘制进度条,其中 ProgressDrawableIndeterminateProgressDrawable 是两种不同的绘制器。

8.1 确定性绘制器 (ProgressDrawable)

确定性绘制器通常由一个背景和一个进度条组成。

1class ProgressDrawable extends LayerDrawable {
2    // ...
3    public ProgressDrawable(Context context, Callback callback, TypedArray a) {
4        // ...
5        // 设置背景层
6        addLayer(mBackground, null);
7        // 设置进度层
8        addLayer(mProgress, null);
9        // ...
10    }
11
12    @Override
13    public void draw(Canvas canvas) {
14        // ...
15        // 绘制背景
16        mBackground.setBounds(getBounds());
17        mBackground.draw(canvas);
18        // ...
19        // 计算进度条的位置
20        Rect bounds = getBounds();
21        int width = bounds.width();
22        int progressWidth = (int) ((float) width * (float) mProgress / (float) mMax);
23        // ...
24        // 绘制进度条
25        mProgress.setBounds(bounds.left, bounds.top, bounds.left + progressWidth, bounds.bottom);
26        mProgress.draw(canvas);
27        // ...
28    }
29}
8.2 不确定性绘制器 (IndeterminateProgressDrawable)

不确定性绘制器通常表现为动画效果。

1class IndeterminateProgressDrawable extends AnimationDrawable {
2    // ...
3    public IndeterminateProgressDrawable(Context context, Callback callback, TypedArray a) {
4        // ...
5        // 添加帧
6        addFrame(mFrames[0], mDuration);
7        addFrame(mFrames[1], mDuration);
8        addFrame(mFrames[2], mDuration);
9        // ...
10    }
11
12    @Override
13    public void draw(Canvas canvas) {
14        // ...
15        // 绘制当前帧
16        super.draw(canvas);
17        // ...
18    }
19}

9. 动画支持

ProgressBar 支持动画效果,特别是在不确定性模式下。

1public void startAnimation(Animation animation) {
2    // ...
3    if (animation != null) {
4        animation.setAnimationListener(mAnimationListener);
5        super.startAnimation(animation);
6    }
7    // ...
8}
9
10private Animation.AnimationListener mAnimationListener = new Animation.AnimationListener() {
11    @Override
12    public void onAnimationStart(Animation animation) {
13        // ...
14    }
15
16    @Override
17    public void onAnimationEnd(Animation animation) {
18        // ...
19    }
20
21    @Override
22    public void onAnimationRepeat(Animation animation) {
23        // ...
24    }
25};

10. 状态变化

ProgressBar 可以根据当前的状态来改变外观。

1@Override
2protected synchronized void drawableStateChanged() {
3    // ...
4    super.drawableStateChanged();
5    // ...
6    // 更新绘制器的状态
7    mIndeterminateProgressDrawable.setState(getDrawableState());
8    mProgressDrawable.setState(getDrawableState());
9    // ...
10}

总结

ProgressBar 的实现基于 View,并使用 Drawable 对象来绘制进度条。它支持确定性和不确定性两种模式,分别通过 ProgressDrawableIndeterminateProgressDrawable 来实现。通过设置进度和最大值,ProgressBar 可以动态地更新进度条的状态,并且支持动画效果。

http://www.lryc.cn/news/408916.html

相关文章:

  • 【HarmonyOS】HarmonyOS NEXT学习日记:七、页面与组件的生命周期
  • 【iOS】——Block循环引用
  • shell脚本自动化安装启动各种服务
  • Python - 开源库 ReportLab 库合并 CVS 和图像生成 PDF 文档
  • Java编写SIP协议
  • 大型语言模型LLM的核心概念
  • 软件测试---网络基础、HTTP
  • 韩顺平0基础学java——第39天
  • Linux文件恢复
  • 大数据的数据质量有效提升的研究
  • Flink-CDC解析(第47天)
  • 二阶段测试
  • CSP-J模拟赛day1——解析+答案
  • 【PostgreSQL案例】我要查的表没有在执行计划中
  • 《程序猿入职必会(5) · CURD 页面细节规范 》
  • 操作系统面试知识点总结5
  • BigInteger和BigDecimal类
  • 2024最新Uniapp的H5网页版添加谷歌授权验证
  • 学习java第一百四十四天
  • Meta 发布 Llama3.1,一站教你如何推理、微调、部署大模型
  • XSSFWorkbook 和 SXSSFWorkbook 的区别
  • 会议主题:NICE Seminar|神经组合优化方法的大规模泛化研究(南方科技大学王振坤副研究员)
  • 昇思25天学习打卡营第22天|CycleGAN图像风格迁移互换
  • 《Java初阶数据结构》----6.<优先级队列之PriorityQueue底层:堆>
  • Matrix Equation(高斯线性异或消元+bitset优化)
  • 【一图学技术】2.API测试9种方法图解
  • 力扣刷题----42. 接雨水
  • 【论文精读】 | 基于图表示的视频抑郁症识别的两阶段时间建模框架
  • 采集PCM,将base64片段转换为wav音频文件
  • eclipse ui bug