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;
 }

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

(0)

相关推荐

  • android自定义进度条渐变色View的实例代码

    最近在公司,项目不是很忙了,偶尔看见一个兄台在CSDN求助,帮忙要一个自定义的渐变色进度条,我当时看了一下进度条,感觉挺漂亮的,就尝试的去自定义view实现了一个,废话不说,先上图吧! 这个自定义的view,完全脱离了android自带的ProgressView,并且没使用一张图片,这样就能更好的降低程序代码上的耦合性! 下面我贴出代码  ,大概讲解一下实现思路吧! 复制代码 代码如下: package com.spring.progressview; import android.conten

  • Android实现环形进度条

    一个通俗易懂的环形进度条,可以定制颜色角度,监听进度. 定义一个attrs.xml <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CircleProgressView"> <!--画笔宽度--> <attr name="progress_width" format=&q

  • Android自定义View实现渐变色进度条

    在网上看到一个进度条效果图,非常美观,如下: 进行效果分解: 1.渐变色,看起来颜色变化并不复杂,使用LinearGradient应该可以实现. 2.圆头,无非是画两个圆,外圆使用渐变色的颜色,内圆固定为白色. 3.灰底,还没有走到的进度部分为灰色. 4.进度值,使用文本来显示: 5.弧形的头部,考虑使用直线进行连接,或者使用曲线,例如贝塞尔曲线: 我首先初步实现了进度条的模样,发现样子有了,却不太美观. 反思了一下,我只是个写代码的,对于哪种比例比较美观,是没有清晰的认识的,所以,还是参考原图

  • Android自定义进度条效果

    最近项目中需要在一个功能模块中使用进度条,效果图如下: 上面图片从左到右分别是效果一,效果二,效果三 需求: 以下四点需要实现 1: 当没有没完成进度的时候,显示效果一 2:当进度完成了一部分,显示图二 3:当进度全部完成之后,显示效果三 4:当进度1到进度2需要动画,进度2到进度3需要动画: 同样进度3到进度2或者进度1也需要动画. 刚开始拿到这个东西的时候,考虑了老长时间,觉得还是有技巧的,先说一下思路吧 首先我们,写一个一模一样的底部布局,如下图1: 图一也就是效果一的全部显示, 图三不是

  • Android 七种进度条的样式

    当一个应用在后台执行时,前台界面就不会有什么信息,这时用户根本不知道程序是否在执行.执行进度如何.应用程序是否遇到错误终止等,这时需要使用进度条来提示用户后台程序执行的进度.Android系统提供了两大类进度条样式,长形进度条(progress-BarStyleHorizontal) 和圆形进度条(progressBarStyleLarge).进度条用处很多,比如,应用程序装载资源和网络连接时,可以提示用户稍等,这一类进度条只是代表应用程序中某一部分的执行情况,而整个应用程序执行情况呢,则可以通

  • Android中实现Webview顶部带进度条的方法

    写这篇文章,做份备忘,简单滴展示一个带进度条的Webview示例,进度条位于Webview上面. 示例图如下: 主Activity代码: 复制代码 代码如下: package com.droidyue.demo.webviewprogressbar; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.vi

  • Android自定义View实现加载进度条效果

    上一篇文章总结了下自定义View的几个步骤,如果还有不清楚的同学可以先去看看Android自定义View(一),这篇文章和大家分享一下自定义加载进度条,效果如下 下面就以水平的进度条为列进行讲解: 1.首先还是在attrs.xml文件中自定义我们需要的属性: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="GradientP

  • Android实现垂直进度条VerticalSeekBar

    本文实例为大家分享了Android实现垂直进度条的具体代码,供大家参考,具体内容如下 水平的进度条见多了,总会想见个垂直的进度条开开眼.今天咱就试试. 要说原理也简单,就是把宽高倒置,其他的理论上都不需要动,发现问题再补补也就行了. 官方提供 官方是提供了垂直进度条的例子源码的,位置在android-sdk-windows\sources\android-23\com\android\example\rscamera\VerticalSeekBar.java,当然首先你SDK中要有Android

  • Android实现弹窗进度条效果

    Android自定义进度条主要是修改ProgressBar的style,弹窗则是在Dialog里显示ProgressBar. 直接上代码. 在style.xml里加入如下代码: <style name="ProgressBar_Mini" parent="@android:style/Widget.ProgressBar.Horizontal"> <item name="android:maxHeight">50dip&l

  • android实现音乐播放器进度条效果

    本文实例为大家分享了android实现音乐播放器进度条效果的具体代码,供大家参考,具体内容如下 效果图 依赖3个对象 MediaPlayer:实现音乐播放,暂停,缓冲. SeekBar:滑动的进度条. java.util.Timer:定时器,时时更新进度条. main.xml样式文件 <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android

随机推荐