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 的构造函数接受 Context、AttributeSet 和 int 类型的默认样式参数。
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 对象来绘制进度条,其中 ProgressDrawable 和 IndeterminateProgressDrawable 是两种不同的绘制器。
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 对象来绘制进度条。它支持确定性和不确定性两种模式,分别通过 ProgressDrawable 和 IndeterminateProgressDrawable 来实现。通过设置进度和最大值,ProgressBar 可以动态地更新进度条的状态,并且支持动画效果。
相关文章:
PrgogressBar实现原理分析
ProgressBar 是 Android 中用于显示进度条的控件,它可以用来表示任务的完成程度或者加载进度等信息。ProgressBar 有两种主要类型:一种是确定性的(determinate),另一种是不确定性的(indeterminateÿ…...
【HarmonyOS】HarmonyOS NEXT学习日记:七、页面与组件的生命周期
【HarmonyOS】HarmonyOS NEXT学习日记:七、页面与组件的生命周期 页面和组件 组件:用Component装饰的代码称为自定义组件页面:Entry装饰的组件即页面的根节点 组件生命周期 aboutToAppear:在创建自定义组件的新实例后…...
【iOS】——Block循环引用
循环引用原因 如果在Block中使用附有_ _strong修饰符的对象类型自动变量,那么当Block从栈复制到堆时,该对象为Block所持有,这样容易引起循环引用。 HPPerson *person [[HPPerson alloc] init];person.block ^{NSLog("person.age--- …...
shell脚本自动化安装启动各种服务
1、自动化配置dns服务器 A主机:vim dns.sh #!/bin/bash# 自动化部署dns# 1、下载bind# 2、修改配置文件# vim /etc/named.conf # listen-on port 53 { 127.0.0.1;any; }; 修改(定位替换)# allow-query { localhost;any; }; 修改&am…...
Python - 开源库 ReportLab 库合并 CVS 和图像生成 PDF 文档
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/140281680 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 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的核心概念
本文主要介绍了目前主流的,几个大型语言模型LLM的整个训练过程 通常分为下面的几个阶段 1. 预训练 采用互联网上的大量数据进行训练,这一阶段大模型LLM的主体已定,找出共性并且压缩成一个模型。模型的参数量不是越大越好,遵循合理…...
软件测试---网络基础、HTTP
一、网络基础 (1)Web和网络知识 网络基础TCP/IP 使用HTTP协议访问Web WWW万维网的诞生 WWW万维网的构成 (2)IP协议 (3)可靠传输的TCP和三次握手策略 (4)域名解析服务DNS ࿰…...
韩顺平0基础学java——第39天
p820-841 jdbc和连接池 1.JDBC为访问不同的数据库提供了统一的接口,为使用者屏蔽了细节问题。 2.Java程序员使用JDBC,可以连接任何提供了JDBC驱动程序的数据库系统,从而完成对数据库的各种操作。 3.jdbc原理图 JDBC带来的好处 2.JDBC带来的…...
Linux文件恢复
很麻烦 一般还是小心最好 特别恢复的时候 可能不能选择某个文件夹去扫描恢复 所以 删除的时候 用rm -i代替rm 一定小心 以及 探索下linux的垃圾箱机制 注意 一定要恢复到不同文件夹 省的出问题 法1 系统自带工具 debugfs 但是好像不能重启? testdisk 1、安装 …...
大数据的数据质量有效提升的研究
大数据的数据质量有效提升是一个涉及多个环节和维度的复杂过程。以下是从数据采集、处理、管理到应用等方面,对大数据数据质量有效提升的研究概述: 一、数据采集阶段 明确采集需求:在数据采集前,需明确数据需求,包括…...
Flink-CDC解析(第47天)
前言 本文主要概述了Flink-CDC. 1. CDC 概述 1.1 什么是CDC? CDC是(Change Data Capture 变更数据获取)的简称 ,在广义的概念上,只要是能捕获数据变更的技术,都可以称之为 CDC。 核心思想是,…...
二阶段测试
二阶段测试 1、部署框架前准备工作 服务器类型部署组件ip地址DR1调度服务器 主(ha01)KeepalivedLVS-DR192.168.168.21DR2调度服务器 备 (ha02)KeepalivedLVS-DR192.168.168.22web1节点服务器 (slave01)NginxTomcatMySQL 备MHA managerMHA node192.168.1…...
CSP-J模拟赛day1——解析+答案
题目传送门 yjq的吉祥数 题解 送分题,暴力枚举即可 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案例】我要查的表没有在执行计划中
问题:查的表没有在执行计划中 sql: 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 页面细节规范 》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...
操作系统面试知识点总结5
#来自ウルトラマンメビウス(梦比优斯) 1 IO管理概述 1.1 I/O 设备 I/O 设备的类型分类。 1.1.1 按使用特性 人机交互类外部设备,例如打印机、显示器等。存储设备,例如磁盘、光盘等。网络通信设备,例如网络接口等。 1…...
BigInteger和BigDecimal类
一、应用场景 1. BigInteger 类 目前,我们学过最大的是long类型,但是,在实际开发时候,很有可能遇见超出long类型范围的数,我们就需要用BigInteger类; ① add 加 ② subtract 减 ③ multiply 乘…...
2024最新Uniapp的H5网页版添加谷歌授权验证
现在教程不少,但是自从谷歌升级验证之后,以前的老教程就失效了,现在写一个新教程以备不时之需。 由于众所周知的特殊原因,开发的时候一定注意网络环境,如果没有梯子是无法进行开发的哦~ clientID的申请方式我就不再进…...
学习java第一百四十四天
Spring通知有哪些类型? 在AOP术语中,切面的工作被称为通知。通知实际上是程序运行时要通过Spring AOP框架来触发的代码段。 Spring切面可以应用5种类型的通知: 前置通知(Before):在目标方法被调用之前调用通…...
LyricsX终极指南:如何在macOS上免费获得完美歌词同步体验
LyricsX终极指南:如何在macOS上免费获得完美歌词同步体验 【免费下载链接】LyricsX 🎶 Ultimate lyrics app for macOS. 项目地址: https://gitcode.com/gh_mirrors/ly/LyricsX 你是否厌倦了在不同音乐播放器间切换时手动搜索歌词?Lyr…...
矩阵键盘原理与实战:从扫描算法到Arduino/CircuitPython驱动指南
1. 项目概述:为什么我们需要矩阵键盘? 在嵌入式项目里,给设备加几个按钮是再常见不过的需求。但如果你需要10个、12个甚至16个独立的按键呢?按照传统思路,一个按键对应一个微控制器的数字输入引脚,那你的Ar…...
Loop窗口管理:终极Mac多窗口高效布局指南
Loop窗口管理:终极Mac多窗口高效布局指南 【免费下载链接】Loop Window management made elegant. 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 你是不是经常在Mac上同时打开十几个窗口,然后迷失在层层叠叠的界面中?写代码…...
5分钟掌握全平台炫酷抽奖:Magpie-LuckyDraw开源项目深度解析
5分钟掌握全平台炫酷抽奖:Magpie-LuckyDraw开源项目深度解析 【免费下载链接】Magpie-LuckyDraw 🏅A fancy lucky-draw tool supporting multiple platforms💻(Mac/Linux/Windows/Web/Docker) 项目地址: https://gitcode.com/gh_mirrors/ma…...
深度解析AzurLaneAutoScript:碧蓝航线自动化脚本的技术架构与应用实践
深度解析AzurLaneAutoScript:碧蓝航线自动化脚本的技术架构与应用实践 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研,全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript…...
通过curl命令调试与验证大模型API连接状态
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 通过curl命令调试与验证大模型API连接状态 基础教程类,针对需要在无SDK环境或快速排错的开发者,详细说明如…...
高效检索句子:基于 SQLite FTS5 的关键词快速匹配方案
std::filesystem::replace_extension 仅修改路径对象的逻辑表示,不更改磁盘文件;真正改后缀需配合 fs::rename,且须检查目标是否存在、文件是否为常规文件,并注意跨卷、文件占用等系统限制。std::filesystem::replace_extension 为…...
AI技能实战指南:从提示工程到RAG与LoRA微调全流程解析
1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的仓库,叫tqviet1978/ai-skills。光看名字,你可能会觉得这又是一个关于“AI技能”的泛泛而谈的教程合集。但点进去仔细研究后,我发现它的定位非常精准,更像是一个为开发者、技…...
AI驱动博客平台CodeBlog-app:开发者技术分享的智能解决方案
1. 项目概述:一个为开发者而生的AI驱动博客平台最近在GitHub上看到一个挺有意思的开源项目,叫CodeBlog-ai/codeblog-app。光看名字,你可能会觉得这又是一个普通的博客系统,或者是一个AI写作工具。但当我深入去研究它的代码和设计理…...
荣品RV1126 SDK编译避坑指南:从环境配置到分区调整,手把手解决常见编译错误
RV1126 SDK编译实战:从环境搭建到分区优化的全流程解决方案 1. 开发环境配置与初始化 RV1126开发环境的搭建是整个开发流程的第一步,也是后续所有工作的基础。一个稳定、高效的开发环境能够显著提升开发效率,减少不必要的错误。 首先需要确保…...
