Android实现带节点的进度条
作者:Silicon_Valley_DH 发布时间:2022-01-16 08:58:02
标签:Android,进度条
日常的开发中经常会需要用到自定义View,这次刚好有个需求,需要用到带有节点的进度条。东西很简单直接继承View就行了。
首先定义一些需要的属性
/**
* 背景画笔
*/
private Paint bgPaint;
/**
* 前景画笔
*/
private Paint forePaint;
/**
* 选中画笔
*/
private Paint selectPaint;
/**
* 未选中画笔
*/
private Paint unselectPaint;
/**
* 背景颜色
*/
private int bgColor = Color.parseColor("#9C9C9C");
/**
* 前景颜色
*/
private int foreColor = Color.parseColor("#8A2BE2");
/**
* 默认高度
*/
private int defaultHeight;
/**
* 节点文字
*/
private List<String> nodeList;
private List<Rect> mBounds;
/**
* 节点圆的半径
*/
private int radius;
/**
* 文字和节点进度条的top
*/
private int marginTop;
/**
* 两个节点之间的距离
*/
private int dividWidth;
/**
* 选中位置
*/
private int selectIndex;
然后在构造方法中初始化这些数据
private void init(Context context) {
radius = SizeUtils.dp2px(context,4);
defaultHeight = SizeUtils.dp2px(context,30);
marginTop = SizeUtils.dp2px(context,5);
bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bgPaint.setColor(bgColor);
bgPaint.setStyle(Paint.Style.FILL);
forePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
forePaint.setColor(foreColor);
forePaint.setStyle(Paint.Style.FILL);
unselectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
unselectPaint.setColor(bgColor);
unselectPaint.setTextSize(SizeUtils.sp2px(context,10));
selectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
selectPaint.setColor(foreColor);
selectPaint.setTextSize(SizeUtils.sp2px(context,10));
}
设置节点文字
/**
* 设置数据
* @param nodeDatas
*/
public void setNodeList(List<String> nodeDatas){
if(nodeDatas != null){
nodeList = nodeDatas;
}
//测量文字所占用的空间
measureText();
}
/**
* 设置选中位置
* @param selectIndex
*/
public void setSelectIndex(int selectIndex){
this.selectIndex = selectIndex;
invalidate();
}
/**
* 测量文字的长宽
*/
private void measureText(){
mBounds = new ArrayList<>();
for (int i = 0; i < nodeList.size(); i++) {
Rect mBound = new Rect();
unselectPaint.getTextBounds(nodeList.get(i),0,nodeList.get(i).length(),mBound);
mBounds.add(mBound);
}
}
最后重要的步骤,开始在onDraw中绘制节点进度条和绘制文字
1、绘制灰色背景线条
if(nodeList == null || nodeList.isEmpty()){
return;
}
bgPaint.setStrokeWidth(radius/2);
//绘制灰色的背景线条
canvas.drawLine(radius,radius,getWidth()-radius,radius,bgPaint);
2、绘制节点上的圆和两个节点之间的间隔线条
//画节点圆
//每个圆相隔的距离
dividWidth = (getWidth()-radius*2)/(nodeList.size() - 1);
forePaint.setStrokeWidth(radius/2);
for (int i = 0; i < nodeList.size(); i++) {
if(i == selectIndex){
for (int j = 0; j <= i; j++) {
canvas.drawCircle(radius+ j * dividWidth, radius, radius , forePaint);
canvas.drawLine(radius,radius,j*dividWidth,radius,forePaint);
}
}else if(i>selectIndex){
canvas.drawCircle(radius + i * dividWidth, radius, radius, bgPaint);
}
}
3、绘制节点上的文字
for (int i = 0; i < nodeList.size(); i++) {
int currentTextWidth=mBounds.get(i).width();
if (i==0){
if (i==selectIndex){
canvas.drawText(nodeList.get(i), 0, radius*2 + marginTop + mBounds.get(i).height()/2, selectPaint);
}else if(i>selectIndex) {
canvas.drawText(nodeList.get(i), 0, radius*2 + marginTop + mBounds.get(i).height()/2, unselectPaint);
}
}else if (i==nodeList.size()-1){
if (i==selectIndex){
for (int j = 0; j <= i; j++) {
if(j == 0){
canvas.drawText(nodeList.get(j), 0, radius*2 + marginTop + mBounds.get(j).height()/2, selectPaint);
}else if(j == i){
canvas.drawText(nodeList.get(j), getWidth() - currentTextWidth, radius*2 + marginTop + mBounds.get(j).height()/2, selectPaint);
}else{
canvas.drawText(nodeList.get(j), radius + j * dividWidth - currentTextWidth / 2, radius*2 + marginTop + mBounds.get(j).height()/2, selectPaint);
}
}
}else if(i>selectIndex) {
canvas.drawText(nodeList.get(i), getWidth() - currentTextWidth, radius*2 + marginTop + mBounds.get(i).height()/2, unselectPaint);
}
}else {
if (i==selectIndex){
for (int j = 0; j <= i; j++) {
if(j>0){
canvas.drawText(nodeList.get(j), radius + j * dividWidth - currentTextWidth / 2, radius*2 + marginTop + mBounds.get(j).height()/2, selectPaint);
}else{
canvas.drawText(nodeList.get(j), 0, radius*2 + marginTop + mBounds.get(j).height()/2, selectPaint);
}
}
}else if(i>selectIndex) {
canvas.drawText(nodeList.get(i), radius + i * dividWidth - currentTextWidth / 2, radius*2 + marginTop + mBounds.get(i).height()/2, unselectPaint);
}
}
}
有时候可能需要的是下面这种进度条
只需要修改onDraw中绘制节点圆和文字的方法就可以了
for (int i=0; i < nodeList.size();i++) {
if (i==selectIndex){
canvas.drawCircle(radius+ i * dividWidth, radius, radius , forePaint);
}else {
canvas.drawCircle(radius + i * dividWidth, radius, radius, bgPaint);
}
}
for (int i=0; i<nodeList.size();i++){
int currentTextWidth=mBounds.get(i).width();
if (i==0){
if (i==selectIndex){
canvas.drawText(nodeList.get(i), 0, radius*2 + marginTop + mBounds.get(i).height()/2, selectPaint);
}else {
canvas.drawText(nodeList.get(i), 0, radius*2 + marginTop + mBounds.get(i).height()/2, unselectPaint);
}
}else if (i==nodeList.size()-1){
if (i==selectIndex){
canvas.drawText(nodeList.get(i), getWidth() - currentTextWidth, radius*2 + marginTop + mBounds.get(i).height()/2, selectPaint);
}else {
canvas.drawText(nodeList.get(i), getWidth() - currentTextWidth, radius*2 + marginTop + mBounds.get(i).height()/2, unselectPaint);
}
}else {
if (i==selectIndex){
canvas.drawText(nodeList.get(i), radius + i * dividWidth - currentTextWidth / 2, radius*2 + marginTop + mBounds.get(i).height()/2, selectPaint);
}else {
canvas.drawText(nodeList.get(i), radius + i * dividWidth - currentTextWidth / 2, radius*2 + marginTop + mBounds.get(i).height()/2, unselectPaint);
}
}
}
点击节点进行节点切换
// 实现节点切换,把注释打开就行了
@Override
public boolean onTouchEvent(MotionEvent event) {
float eventX;
float eventY;
int i = event.getAction();
if (i == MotionEvent.ACTION_DOWN) {
} else if (i == MotionEvent.ACTION_MOVE) {
} else if (i == MotionEvent.ACTION_UP) {
eventX = event.getX();
eventY = event.getY();
//计算选中的index
float select = eventX / dividWidth;
float xs = select - (int) (select);
//selectIndex = (int) select + (xs > 0.5 ? 1 : 0);
}
//invalidate();
return true;
}
来源:https://blog.csdn.net/u013855006/article/details/81157618


猜你喜欢
- SpringBoot获取所有接口的路由@Autowired WebApplicationContext appli
- Android的遮罩效果就是把一张图片盖在另一张图片的上面,通过控制任意一张图片的显示百分比实现遮罩效果。下面我使用两张一样的图片来实现一个
- 本文实例讲述了Android编程开发之ScrollView嵌套GridView的方法。分享给大家供大家参考,具体如下:前些日子在开发中用到了
- java中next与nextLine用法区别:next()一定要读取到有效字符后才可以结束输入,对输入有效字符之前遇到的空格键、Tab键或E
- 简介Spring Security,这是一种基于 Spring AOP 和 Servlet 过滤器的安全框架。它提供全面的安全性解决方案,同
- C# Linq延迟查询在定义linq查询表达式时,查询是不会执行,查询会在迭代数据项时运行。它使用yield return 语句返回谓词为t
- 前言随着网络技术的发展、计算机应用水平广泛提高,原来系统的时效性、数据的正确性、操作的方便性上都存在不足,已影响到系统的正常使用。经过考察比
- 1,验证传入路径是否为正确的路径名(Windows系统,其他系统未使用)Java代码 // 验证字符串是否为正确路径名的正则表达式 
- 概述:@ResponseBody @RequestMapping(value="/download/{fileName:[a-zA
- 2018年3月20日,Oracle发布java10。java10为java带来了很多新特性,其中让人眼前一亮的便是var关键字的引入。wha
- 博主最近在做一个内网项目,内部可以访问外部数据,但是外部访问不了内部数据,这也就造成了可能文件无法上传,所以博主另辟蹊径,在本地服务器上建立
- Hi~大家好,出来创业快3个月了,一切还不错,前一段时间用了业余时间搞了个问答类网站YQMA.想做中国的stackoverflow,哈哈,只
- 前言dynamic-tp是一个轻量级的动态线程池插件,它是一个基于配置中心的动态线程池,线程池的参数可以通过配置中心配置进行动态的修改,在配
- 前言当我们通过前端向后端发起一个请求调用后端接口时,经常会遇到404的问题。网上关于对404问题介绍的一大堆,其实404问题的本质就两点。在
- @PostConstruct不被调用的原因如果在配置文件中配置使用,延迟加载的话如图被@Service等注解的类,需要在注入使用的时候,才会
- 应用场景:当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退给买家,微信支付将在收到退款请求并且验证
- SWF Tools 是一组用来处理 Flash 的 swf 文件的工具包,包括:1. 合并工具 swfcombine2. 抽取工具 swfe
- 使用例子如下,用JAVA 运行Sort1, 输入你要排序的文件路径 , 如 例子是对H:\下的文件和它所有子文件夹下的文件进行排序2, 输入
- 比如要获取打开摄像头的应用程序名称,只需要在frameworks/base/core/android/hardware/Camera.jav
- 前言使用Java8的新特性Stream流式处理,可以提高对于集合的一些操作效率,再配合lambda表达式,可以极致的简化代码,尤其还有并行流