Android自定义View完美实现指示器位置随进度变化的IndicateProgressView

2023-11-02

该文章同步发布在公众号”LinminTech”上,请在本文最后扫码关注,获取更多精彩Android开发文章。

效果图

这里写图片描述

需求

在平时开发过程中,UI经常要求实现如上图所示的ProgressBar,但是Android系统自带的ProgressBar并不能满足我们的要求,这就要求我们自定义实现这样的控件。

基本原理

在网上看到很多类似直接继承系统ProgressBar来实现此控件,但是在实现进度指示器都比较复杂,这里介绍一种比较简单的实现方式。
基本原理:

第一步画Progress默认背景矩形框

此默认背景矩形框铺满我们自己定义的宽度。代码如下

int width = getWidth();
int height = getHeight();

//画背景
RectF backRectF = new RectF(0, height * 2 / 5, width, height * 3 / 5);
backPaint.setColor(backgroundColor);
canvas.drawRoundRect(backRectF, radius, radius, backPaint);

第二步画Progress进度矩形框

此进度矩形框是盖在背景矩形框之上的。

//画进度
RectF progressRectF = new RectF(0, height * 2 / 5, width * getScale(), height * 3 / 5);
LinearGradient lGradient = new LinearGradient(0, height * 2 / 5, width * getScale(), height * 3 / 5, startProgressColor, endProgressColor, Shader.TileMode.MIRROR);
progressPaint.setShader(lGradient);
canvas.drawRoundRect(progressRectF, radius, radius, progressPaint);

第三步画进度百分比指示器矩形框

此进度百分比指示器是盖在进度矩形框之上。

//画指示器边框
float left = width * getScale() - indicateTextPaint.measureText(PERCENT_STR) - defaultIndicateMargin;
float right = width * getScale();
if (getScale() <= 0.5) {
    left = width * getScale() - defaultIndicateMargin;
    right = left + indicateTextPaint.measureText(PERCENT_STR) +   defaultIndicateMargin;
}
if (left <= 0f) {
    left = 0f;
    right = indicateTextPaint.measureText(PERCENT_STR) + defaultIndicateMargin;
}
if (right <= indicateTextPaint.measureText(PERCENT_STR) + defaultIndicateMargin) {
    right = indicateTextPaint.measureText(PERCENT_STR) + defaultIndicateMargin;
}
RectF indicatorRectF = new RectF(left, height / 5, right, height * 4 / 5);
indicateBackPaint.setColor(indicateTextColor);
canvas.drawRoundRect(indicatorRectF, indicatorRadius, indicatorRadius, indicateBackPaint);

//画指示器内部为白色
RectF indicatorContentRectF = new RectF(left + defaultContentMargin, height / 5 + defaultContentMargin,right - defaultContentMargin, height * 4 / 5 - defaultContentMargin);
indicateBackPaint.setColor(Color.WHITE);
canvas.drawRoundRect(indicatorContentRectF, indicatorRadius, indicatorRadius, indicateBackPaint);

第四步画进度百分比文本

此文本是在指示器内部显示。

//画指示器文本
float textX = indicatorContentRectF.centerX() - indicateTextPaint.measureText(indicateText) / 2;
float textY = height * 3 / 5;
canvas.drawText(indicateText, textX, textY, indicateTextPaint);

几个要点说明

说明图
这篇文章我介绍的实现方法,比较麻烦的是进度指示器indicator的坐标、进度百分比文本的坐标,以及自定义颜色渐变的实现。这里我们假设定义indicator的宽度为indicator.width。

确定进度指示器的坐标

图一:
indicator的最右边与进度条progress最右边重合,所以indicator.x为进度条progress.right - - defaultIndicateMargin(默认间距)。
图二:
indicator在最左端时,indicator.x为0,indicator.right为indicator.width。
图三:
indicator在最右端时,indicator.right为整个view的width,indicator.x为width - indicator.width。

确定进度百分比文本的坐标

以上任一种情况下,进度百分比文本的坐标text.x,text.y是怎样的呢?
text.x = indicatoRectF.centerX - indicatorTextPaint.measure(“百分比文本”) / 2,
因为此文本一直都是垂直居中的(我是整个view的高度分为5等份,进度条占1等份,指示器indicator占3等份,上下空白各占1等份),text.y(text.baseline) = view.height * 3 / 5。

颜色渐变的实现

利用线性颜色渐变LinearGradient来实现,如下:

LinearGradient lGradient = new LinearGradient(0, height * 2 / 5, width * getScale(), height * 3 / 5, startProgressColor, endProgressColor, Shader.TileMode.MIRROR);
progressPaint.setShader(lGradient);

源码下载

IndicateProgress源码下载

扫码关注,获取更多精彩Android开发文章
LinminTech

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android自定义View完美实现指示器位置随进度变化的IndicateProgressView 的相关文章

  • Firebase 管理 SDK Android

    在 Android 中初始化 Firebase Admin SDK 的代码 Override protected void onCreate Bundle savedInstanceState super onCreate savedIns
  • 在应用程序简历中隐藏软键盘

    我有一个 Android 应用程序 使用 Xamarin 用 C 编写 我已将应用程序简化为包含 TextView 和用于横幅广告的 Google admod AdView 的 LinearLayout 我不希望软键盘出现在应用程序中 这不
  • getItem 与 getItemAtPosition

    有两种方法可以获取列表视图中的选定项目 list getAdapter getItem position list getItemAtPosition position 我的问题是 哪一种是首选的做法 我见过人们同时使用这两种方法 您可以使
  • 为什么将函数参数声明为最终的?

    我目前正在阅读 Sams 出版的 24 小时自学 Android 应用程序开发 一书 我对 Java Android 或其他方面还比较陌生 我对 ActionScript 3 有非常扎实的背景 它与 Java 有足够的相似之处 因此该语言本
  • 共同的偏好不断消失

    我正在使用共享首选项来存储我的应用程序的登录凭据 除了一个用户之外 一切正常 一段时间后 共享偏好似乎会以某种方式重置或清除 我已针对该用户调整了我的应用程序 使其不再清除他的共享偏好设置 这样我就可以确定这不是我的应用程序的错 但即使在这
  • 接近语法错误(代码1)插入Android SQLite

    我正在创建一个通讯录应用程序 用户可以在其中输入姓名 电子邮件地址和号码 我希望将此数据保存在数据库中 但我似乎无法使插入方法起作用 我收到的错误是 android database sqlite SQLiteException near
  • 线程自动利用多个CPU核心?

    假设我的应用程序运行 2 个线程 例如渲染线程和游戏更新线程 如果它在具有多核 CPU 当今典型 的移动设备上运行 我是否可以期望线程在可能的情况下自动分配给不同的核心 我知道底层操作系统内核 Android linux内核 决定调度 我的
  • 已经使用 AsyncTask doInBackground 但新数据未显示

    我使用 AsyncTask 创建一个聊天室来接收消息 因此它总是检查即将到来的消息并将其显示给客户端 但代码似乎无法按我希望的方式工作 在客户端只显示所有旧数据 新数据不显示 因为当我尝试从服务器发送消息时 新数据没有显示在客户端中 我对这
  • 更新到材质 1.2.0 后,材质按钮上缺少圆角半径属性

    这是我的材质按钮代码
  • Firebase:如何在Android应用程序中设置默认通知渠道?

    如何设置default通知渠道通知消息当应用程序在后台运行时会出现什么情况 默认情况下 这些消息使用 杂项 通道 如你看到的在官方文档中 https firebase google com docs cloud messaging andr
  • 请求位置更新参数

    这就是 requestLocationUpdates 的样子 我使用它的方式 requestLocationUpdates String provider long minTime float minDistance LocationLis
  • 带有自定义阵列适配器的微调器不允许选择项目

    我使用自定义阵列适配器作为微调器 但是 当在下拉列表中选择一个项目时 下拉列表保留在那里 并且微调器不会更新 这是错误行为 与使用带有字符串的通用数组适配器相比 这是自定义类 我错过了什么吗 谢谢 public class Calendar
  • Android 启动器快捷方式

    我制作了一个简单的打卡 打卡时钟应用程序 我想向用户添加在主屏幕上创建快捷方式的选项 该快捷方式将切换应用程序的状态 超时 超时 但我根本不希望此快捷方式在屏幕上打开应用程序 这是我的 setupShortcut private void
  • 从 android 简单上传到 S3

    我在网上搜索了从 android 上传简单文件到 s3 的方法 但找不到任何有效的方法 我认为这是因为缺乏具体步骤 1 https mobile awsblog com post Tx1V588RKX5XPQB TransferManage
  • Android Studio:无法启动守护进程

    当我尝试在 Android Studio 中导入 gradle 项目时 遇到以下错误 Unable to start the daemon process This problem might be caused by incorrect
  • 如何在不更改手机语言的情况下更改Android应用程序语言?

    我希望用户在应用程序内选择一种语言 选择语言后 我希望字符串使用特定语言 如果我更改手机语言 那么我的应用程序将以设置的语言运行 我无法找到任何在不更改手机语言的情况下设置语言的方法 此外 一旦设置了语言 更改就应该反映出来 有人可以建议一
  • 材质设计图标颜色

    应该是哪种颜色 暗 材质图标 在官方文档上 https www google com design spec style icons html icons system icons https www google com design s
  • 在 Android 上按下电源按钮时,如何防止先调用 onDestroy() 再调用 onCreate()

    我正在记录每个 onCreate 和 onDestroy 调用 我发现 一旦我单击 Android 上的电源按钮 以及模拟器上的电源按钮 我的活动中就会拨打电话 gt onDestroy gt onCreate 这会杀死我的游戏 然后立即从
  • android Accessibility-service 突然停止触发事件

    我有一个 AccessibilityService 工作正常 但由于开发过程中的某些原因它停止工作 我似乎找不到这个原因 请看一下我的代码并告诉我为什么它不起作用 public class MyServicee extends Access
  • 如何将图像从 Android 应用程序上传到网络服务器的特定文件夹中

    如何将图像从 android 移动到 Web 服务器上的指定文件夹 这是我的安卓代码 package com example bitmaptest import java io ByteArrayOutputStream import ja

随机推荐

  • unity游戏开发入门——加载场景的方式

    unity加载场景的四种方式分别是 1 Application LoadLevel 同步载入 如果当前场景为A 我们要切换到场景B unity会在切换场景的时候将场景B中的全部内容 场景B中全部的静态物体 不包含兴许代码中Instantia
  • unity C# 使用 action实现函数回调和 委托(Delegate)

    一 C 使用 action实现函数回调 1 1 声明一个方法 这个方法需要传递进去一个函数 并且这个传递进去的函数也是需要参数的 我们把它声明为Action
  • unity 计时器

    unity 计数器 计时器就是在游戏界面的时间 可以是一个正计时 也可以是倒计时 现在简单分享一下简单的计时代码 private void Update totalTime Time deltaTime if totalTime lt 0
  • SpringCloud的搭建

    SpringCloud的搭建 源码 Eureka的创建步骤 最终版为2021 5 23版本 每次提交对应下面的一个步骤 1 Eureka保证AP 2 Eureka的使用 Ribbon的使用步骤 最终版为2021 5 24版本 每次提交对应下
  • Hive SQL中的lateral view explode

    公众号后台回复 图书 了解更多号主新书内容 作者 胖里 来源 胖里的日常 标题中直接写lateral view explode是我鲁莽了 毕竟这俩不是法定cp 也并不是不能分开各自生活 其中explode可以放在select从句中单独使用
  • android ScrollView 嵌套RecyclerView 解决滑动冲突

    为了解决滑动事件的冲突需要重写ScrollView Copyright 2014 Soichiro Kashima Licensed under the Apache License Version 2 0 the License you
  • 【Linux

    目录 一 判断文件是否存在 1 1 判断目录是否存在 1 2 判断文件是否存在 1 3 其他文件类型判断 二 字符串截取 去掉文件后缀 2 1 获取文件后缀 2 2 获取文件前缀 在Linux编程过程中 设计到对文件的处理时常常需要判断某个
  • 远程调试运行在Resin上面的Web应用程序

    为什么80 的码农都做不了架构师 gt gt gt 有时候 我们不得不放弃在本地调试我们的程序 把我们的程序先布署到服务器 然后把调试信息都记在日志中 用眼睛瞅日志来调试程序 不是用这种方式不行 只是效率太低 本来写程序是一件开心的事情 却
  • UE4数字孪生项目制作规范

    UE数字孪生项目制作规范 说明 协同 规范 说明 UnrealEngine项目 打包输出Window应用 鼠标操作 键盘快捷键操作 协同 内部开发的可以自己内网搭建svn服务器协同开发 如有外部人员参与项目开发 则项目协同可使用svnbuc
  • Spring Boot:jar中没有主清单属性

    D hu git spring xxx xxx target gt java jar spring cloud eureka 0 0 1 SNAPS HOT jar spring xxx xxx 0 0 1 SNAPSHOT jar中没有主
  • 数据库的背景知识及基本概念

    数据库的背景知识及基本概念 随着互联网技术的高速发展 大量的数据正在不断产生 伴随而来的是如何安全有效的存储 检索 管理他们 使用数据库可以高效且条理分明地存储数据 它使人们能够更加迅速和方便管理数据 主要体现一下几个方面 可以结构化存储大
  • 奥迪A6 C5空调制冷效果差维修

    一台2003年出厂的一汽奥迪A6 C5 2 8L轿车 装备BBG发动机及双区自动空调 行驶约159000公里 该车空调制冷效果差 空调面板设定22度 用手感知出风口温度 凉 但不够凉 压缩机离合器正常吸合 皮带盘正常运行 连接空调歧管压力表
  • 从零读懂CAN总线(上)

    概要 上世纪八十年代以来 汽车ECU越来越多 如ABS 电控门窗 电子燃油喷射装置 如果仍然采用常规的点对点布线方式 即电线一段与开关相接 另一端与用电设备相通 将会导致车上电线数目的急剧增加 从而带来线束的冗余及维修成本的提高 这就对汽车
  • Gorm系列之1

    Gorm系列之1 特别指出 特别指出的是 该系列基础代码来自git上的开源项目7days golang 项目地址 https github com geektutu 7days golang 原项目作者 极客兔兔 个人主页 https ge
  • 网络面试题及答案

    1 标准网络线的颜色排列顺序 568B 橙白 橙 绿白 蓝 蓝白 绿 棕白 棕 568A 绿白 绿 橙白 蓝 蓝白 橙 棕白 棕 直通线一般都用 A线序或 B线序 交叉线一端是 568A 一端 是 568B 2 按照数据访问速度排序 硬盘
  • linux内存调试工具集

    除了GDB以外 linux还提供了很多的内存调试工具 注意 以下工具的使用之前 gcc需要使用 g编译出带符号的elf 1 addr2line 用于将可执行文件的虚拟内存地址或者动态库的偏移量转换成函数以及代码行 动态库的偏移量计算方式 将
  • 用python和计算机对话(计算机的语句)

    计算机中的的语句 编程其实就是一个把人类语言转换成计算机语言的过程 再知道每个字是什么意思后 就要把它连成一句话 这样它便有了意义 程序便是由这样一句一句的计算机语句组成的 那么计算机语句都有哪些呢 1 if else语句 if是如果的意思
  • 字节原来这么容易进,是面试官放水,还是公司实在是太缺人?

    本人211非科班 之前在字节和腾讯实习过 这次其实没抱着什么特别大的希望投递 没想到字节可以再给我一次机会 还是挺开心的 本来以为有个机会就不错啦 没想到能成功上岸 在这里要特别感谢帮我内推的同学 中间投递比较曲折 是他帮了我很多 非常负责
  • onlyoffice文档服务器加载慢,【onlyoffice中文指南】12-问题及排除

    作者 日期 雨中星辰 2018 12 20 故障排除 编辑器集成中最常见的问题及解决方法 下载失败 Download failed 下载失败 编辑器加载过程中将显示 下载失败 消息 该文档编辑服务不能上传文件进行编辑 检查document
  • Android自定义View完美实现指示器位置随进度变化的IndicateProgressView

    该文章同步发布在公众号 LinminTech 上 请在本文最后扫码关注 获取更多精彩Android开发文章 效果图 需求 在平时开发过程中 UI经常要求实现如上图所示的ProgressBar 但是Android系统自带的ProgressBa