当前位置: 首页 > 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 可以动态地更新进度条的状态,并且支持动画效果。

相关文章:

PrgogressBar实现原理分析

ProgressBar 是 Android 中用于显示进度条的控件&#xff0c;它可以用来表示任务的完成程度或者加载进度等信息。ProgressBar 有两种主要类型&#xff1a;一种是确定性的&#xff08;determinate&#xff09;&#xff0c;另一种是不确定性的&#xff08;indeterminate&#xff…...

【HarmonyOS】HarmonyOS NEXT学习日记:七、页面与组件的生命周期

【HarmonyOS】HarmonyOS NEXT学习日记&#xff1a;七、页面与组件的生命周期 页面和组件 组件&#xff1a;用Component装饰的代码称为自定义组件页面&#xff1a;Entry装饰的组件即页面的根节点 组件生命周期 aboutToAppear&#xff1a;在创建自定义组件的新实例后&#xf…...

【iOS】——Block循环引用

循环引用原因 如果在Block中使用附有_ _strong修饰符的对象类型自动变量&#xff0c;那么当Block从栈复制到堆时&#xff0c;该对象为Block所持有&#xff0c;这样容易引起循环引用。 HPPerson *person [[HPPerson alloc] init];person.block ^{NSLog("person.age--- …...

shell脚本自动化安装启动各种服务

1、自动化配置dns服务器 A主机&#xff1a;vim dns.sh #!/bin/bash# 自动化部署dns# 1、下载bind# 2、修改配置文件# vim /etc/named.conf # listen-on port 53 { 127.0.0.1;any; }; 修改&#xff08;定位替换&#xff09;# allow-query { localhost;any; }; 修改&am…...

Python - 开源库 ReportLab 库合并 CVS 和图像生成 PDF 文档

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/140281680 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Report…...

Java编写SIP协议

1、编写Server代码 package com.genersoft.iot.vmp.sip; import javax.sip.*; import javax.sip.message.*; import javax.sip.header.*; import java.util.*;public class SimpleSipServer implements SipListener {private SipFactory sipFactory;private SipStack sipStack…...

大型语言模型LLM的核心概念

本文主要介绍了目前主流的&#xff0c;几个大型语言模型LLM的整个训练过程 通常分为下面的几个阶段 1. 预训练 采用互联网上的大量数据进行训练&#xff0c;这一阶段大模型LLM的主体已定&#xff0c;找出共性并且压缩成一个模型。模型的参数量不是越大越好&#xff0c;遵循合理…...

软件测试---网络基础、HTTP

一、网络基础 &#xff08;1&#xff09;Web和网络知识 网络基础TCP/IP 使用HTTP协议访问Web WWW万维网的诞生 WWW万维网的构成 &#xff08;2&#xff09;IP协议 &#xff08;3&#xff09;可靠传输的TCP和三次握手策略 &#xff08;4&#xff09;域名解析服务DNS &#xff0…...

韩顺平0基础学java——第39天

p820-841 jdbc和连接池 1.JDBC为访问不同的数据库提供了统一的接口&#xff0c;为使用者屏蔽了细节问题。 2.Java程序员使用JDBC&#xff0c;可以连接任何提供了JDBC驱动程序的数据库系统&#xff0c;从而完成对数据库的各种操作。 3.jdbc原理图 JDBC带来的好处 2.JDBC带来的…...

Linux文件恢复

很麻烦 一般还是小心最好 特别恢复的时候 可能不能选择某个文件夹去扫描恢复 所以 删除的时候 用rm -i代替rm 一定小心 以及 探索下linux的垃圾箱机制 注意 一定要恢复到不同文件夹 省的出问题 法1 系统自带工具 debugfs 但是好像不能重启&#xff1f; testdisk 1、安装 …...

大数据的数据质量有效提升的研究

大数据的数据质量有效提升是一个涉及多个环节和维度的复杂过程。以下是从数据采集、处理、管理到应用等方面&#xff0c;对大数据数据质量有效提升的研究概述&#xff1a; 一、数据采集阶段 明确采集需求&#xff1a;在数据采集前&#xff0c;需明确数据需求&#xff0c;包括…...

Flink-CDC解析(第47天)

前言 本文主要概述了Flink-CDC. 1. CDC 概述 1.1 什么是CDC&#xff1f; CDC是&#xff08;Change Data Capture 变更数据获取&#xff09;的简称 &#xff0c;在广义的概念上&#xff0c;只要是能捕获数据变更的技术&#xff0c;都可以称之为 CDC。 核心思想是&#xff0c…...

二阶段测试

二阶段测试 1、部署框架前准备工作 服务器类型部署组件ip地址DR1调度服务器 主&#xff08;ha01&#xff09;KeepalivedLVS-DR192.168.168.21DR2调度服务器 备 (ha02)KeepalivedLVS-DR192.168.168.22web1节点服务器 (slave01)NginxTomcatMySQL 备MHA managerMHA node192.168.1…...

CSP-J模拟赛day1——解析+答案

题目传送门 yjq的吉祥数 题解 送分题&#xff0c;暴力枚举即可 Code #include<bits/stdc.h> using namespace std;int l,r; int num1,tmp0,q[10000],a[10000]; int k (int x){for (int j1;j<tmp;j){if (xq[j])return 0;}return 1; } int main(){while (num<100…...

【PostgreSQL案例】我要查的表没有在执行计划中

问题&#xff1a;查的表没有在执行计划中 sql&#xff1a; SELECT* FROM(SELECTA.column1 as "column1",--中间省略很多A字段A.column99 as "column99"fromtable_a Aleft join (SELECTlzl_idfromtable_a AAinner join table_b BB ON AA.lzl_key BB.lzl_…...

《程序猿入职必会(5) · CURD 页面细节规范 》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

操作系统面试知识点总结5

#来自ウルトラマンメビウス&#xff08;梦比优斯&#xff09; 1 IO管理概述 1.1 I/O 设备 I/O 设备的类型分类。 1.1.1 按使用特性 人机交互类外部设备&#xff0c;例如打印机、显示器等。存储设备&#xff0c;例如磁盘、光盘等。网络通信设备&#xff0c;例如网络接口等。 1…...

BigInteger和BigDecimal类

一、应用场景 1. BigInteger 类 目前&#xff0c;我们学过最大的是long类型&#xff0c;但是&#xff0c;在实际开发时候&#xff0c;很有可能遇见超出long类型范围的数&#xff0c;我们就需要用BigInteger类&#xff1b; ① add 加 ② subtract 减 ③ multiply 乘…...

2024最新Uniapp的H5网页版添加谷歌授权验证

现在教程不少&#xff0c;但是自从谷歌升级验证之后&#xff0c;以前的老教程就失效了&#xff0c;现在写一个新教程以备不时之需。 由于众所周知的特殊原因&#xff0c;开发的时候一定注意网络环境&#xff0c;如果没有梯子是无法进行开发的哦~ clientID的申请方式我就不再进…...

学习java第一百四十四天

Spring通知有哪些类型&#xff1f; 在AOP术语中&#xff0c;切面的工作被称为通知。通知实际上是程序运行时要通过Spring AOP框架来触发的代码段。 Spring切面可以应用5种类型的通知&#xff1a; 前置通知&#xff08;Before&#xff09;&#xff1a;在目标方法被调用之前调用通…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统&#xff0c;它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间&#xff0c;使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的&#xff0c;要在 …...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

算术操作符与类型转换:从基础到精通

目录 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符&#xff1a;、-、*、/、% 赋值操作符&#xff1a;和复合赋值 单⽬操作符&#xff1a;、--、、- 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...

对象回调初步研究

_OBJECT_TYPE结构分析 在介绍什么是对象回调前&#xff0c;首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例&#xff0c;用_OBJECT_TYPE这个结构来解析它&#xff0c;0x80处就是今天要介绍的回调链表&#xff0c;但是先不着急&#xff0c;先把目光…...