Android实现带节点的进度条

 更新时间:2020年03月26日 10:17:27   作者:Silicon_Valley_DH  
这篇文章主要为大家详细介绍了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;
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Android compose气泡升起和水滴下坠动画实现示例

    Android compose气泡升起和水滴下坠动画实现示例

    这篇文章主要为大家介绍了Android compose气泡升起和水滴下坠动画实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Android XmlPullParser 方式解析 Xml 文档

    Android XmlPullParser 方式解析 Xml 文档

    这篇文章主要介绍了Android XmlPullParser 方式解析 Xml 文档的相关资料,需要的朋友可以参考下
    2017-06-06
  • 如何安装系统认证签名过的APK

    如何安装系统认证签名过的APK

    如果你的App因为权限原因需要设置 android:sharedUserId="android.uid.system" 那么IDE编译出的包通常是无法直接安装的,查看控制台会发现报 INSTALL_FAILED_SHARED_USER_INCOMPATIBLE错误。这是必须的,随随便便一个App声明一下就可以和系统用户共享ID,岂不乱套了?
    2014-07-07
  • Android UI绘制流程及原理详解

    Android UI绘制流程及原理详解

    在本篇文章里小编给大家整理的是关于Android UI绘制流程及原理以及相关知识点,需要的朋友们可以学习下。
    2019-08-08
  • Android基于Xposed修改微信运动步数实例

    Android基于Xposed修改微信运动步数实例

    这篇文章主要介绍了Android基于Xposed修改微信运动步数实例,需要的朋友可以参考下
    2017-06-06
  • Android四大组件之broadcast广播详解

    Android四大组件之broadcast广播详解

    Android开发的四大组件分别是:活动(activity),用于表现功能;服务(service),后台运行服务,不提供界面呈现;广播接受者(Broadcast Receive),勇于接收广播;内容提供者(Content Provider),支持多个应用中存储和读取数据,相当于数据库,本篇着重介绍广播组件
    2022-10-10
  • Android实现QQ侧滑(删除、置顶等)功能

    Android实现QQ侧滑(删除、置顶等)功能

    这篇文章主要为大家详细介绍了Android实现QQ侧滑删除、置顶等功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • Android 一键清理、内存清理功能实现

    Android 一键清理、内存清理功能实现

    这篇文章主要介绍了Android 一键清理、内存清理功能实现,非常具有实用价值,需要的朋友可以参考下。
    2017-01-01
  • Android仿微信列表滑动删除之可滑动控件(一)

    Android仿微信列表滑动删除之可滑动控件(一)

    这篇文章主要为大家详细介绍了Android仿微信列表滑动删除之可滑动控件,具有一定的实用性和参考价值,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • Android开发使用Databinding实现关注功能mvvp

    Android开发使用Databinding实现关注功能mvvp

    这篇文章主要为大家介绍了Android开发使用Databinding实现关注功能mvvp示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09

最新评论