本博文包含两个组件,首先上效果图:

1.ProgressBarView1(支持拖动):


2.ProgressBarView2(不同进度值显示不同颜色,不支持拖拽):


代码不多,注释也比较详细,全部贴上了:

(一)ProgressBarView1:

/*** 自定义绚丽的ProgressBar.*/public class ProgressBarView1 extends View {  /**  * 进度条所占用的角度  */  private static final int ARC_FULL_DEGREE = 300;  /**  * 弧线的宽度  */  private int STROKE_WIDTH;  /**  * 组件的宽,高  */  private int width, height;  /**  * 进度条最大值和当前进度值  */  private float max, progress;  /**  * 是否允许拖动进度条  */  private boolean draggingEnabled = false;  /**  * 绘制弧线的矩形区域  */  private RectF circleRectF;  /**  * 绘制弧线的画笔  */  private Paint progressPaint;  /**  * 绘制文字的画笔  */  private Paint textPaint;  /**  * 绘制当前进度值的画笔  */  private Paint thumbPaint;  /**  * 圆弧的半径  */  private int circleRadius;  /**  * 圆弧圆心位置  */  private int centerX, centerY;  public ProgressBarView1(Context context) {    super(context);    init();  }  public ProgressBarView1(Context context, AttributeSet attrs) {    super(context, attrs);    init();  }  public ProgressBarView1(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);    init();  }  private void init() {    progressPaint = new Paint();    progressPaint.setAntiAlias(true);    textPaint = new Paint();    textPaint.setColor(Color.WHITE);    textPaint.setAntiAlias(true);    thumbPaint = new Paint();    thumbPaint.setAntiAlias(true);    //使用自定义字体    textPaint.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fangz.ttf"));  }  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    if (width == 0 || height == 0) {      width = getWidth();      height = getHeight();      //计算圆弧半径和圆心点      circleRadius = Math.min(width, height) / 2;      STROKE_WIDTH = circleRadius / 12;      circleRadius -= STROKE_WIDTH;      centerX = width / 2;      centerY = height / 2;      //圆弧所在矩形区域      circleRectF = new RectF();      circleRectF.left = centerX - circleRadius;      circleRectF.top = centerY - circleRadius;      circleRectF.right = centerX + circleRadius;      circleRectF.bottom = centerY + circleRadius;    }  }  private Rect textBounds = new Rect();  @Override  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    float start = 90 + ((360 - ARC_FULL_DEGREE) >> 1); //进度条起始点    float sweep1 = ARC_FULL_DEGREE * (progress / max); //进度划过的角度    float sweep2 = ARC_FULL_DEGREE - sweep1; //剩余的角度    //绘制起始位置小圆形    progressPaint.setColor(Color.WHITE);    progressPaint.setStrokeWidth(0);    progressPaint.setStyle(Paint.Style.FILL);    float radians = (float) (((360.0f - ARC_FULL_DEGREE) / 2) / 180 * Math.PI);    float startX = centerX - circleRadius * (float) Math.sin(radians);    float startY = centerY + circleRadius * (float) Math.cos(radians);    canvas.drawCircle(startX, startY, STROKE_WIDTH / 2, progressPaint);    //绘制进度条    progressPaint.setStrokeWidth(STROKE_WIDTH);    progressPaint.setStyle(Paint.Style.STROKE);//设置空心    canvas.drawArc(circleRectF, start, sweep1, false, progressPaint);    //绘制进度条背景    progressPaint.setColor(Color.parseColor("#d64444"));    canvas.drawArc(circleRectF, start + sweep1, sweep2, false, progressPaint);    //绘制结束位置小圆形    progressPaint.setStrokeWidth(0);    progressPaint.setStyle(Paint.Style.FILL);    float endX = centerX + circleRadius * (float) Math.sin(radians);    float endY = centerY + circleRadius * (float) Math.cos(radians);    canvas.drawCircle(endX, endY, STROKE_WIDTH / 2, progressPaint);    //上一行文字    textPaint.setTextSize(circleRadius >> 1);    String text = (int) (100 * progress / max) + "";    float textLen = textPaint.measureText(text);    //计算文字高度    textPaint.getTextBounds("8", 0, 1, textBounds);    float h1 = textBounds.height();    //% 前面的数字水平居中,适当调整    float extra = text.startsWith("1") ? -textPaint.measureText("1") / 2 : 0;    canvas.drawText(text, centerX - textLen / 2 + extra, centerY - 30 + h1 / 2, textPaint);    //百分号    textPaint.setTextSize(circleRadius >> 2);    canvas.drawText("%", centerX + textLen / 2 + extra + 5, centerY - 30 + h1 / 2, textPaint);    //下一行文字    textPaint.setTextSize(circleRadius / 5);    text = "可用内存充足";    textLen = textPaint.measureText(text);    textPaint.getTextBounds(text, 0, text.length(), textBounds);    float h2 = textBounds.height();    canvas.drawText(text, centerX - textLen / 2, centerY + h1 / 2 + h2, textPaint);    //绘制进度位置,也可以直接替换成一张图片    float progressRadians = (float) (((360.0f - ARC_FULL_DEGREE) / 2 + sweep1) / 180 * Math.PI);    float thumbX = centerX - circleRadius * (float) Math.sin(progressRadians);    float thumbY = centerY + circleRadius * (float) Math.cos(progressRadians);    thumbPaint.setColor(Color.parseColor("#33d64444"));    canvas.drawCircle(thumbX, thumbY, STROKE_WIDTH * 2.0f, thumbPaint);    thumbPaint.setColor(Color.parseColor("#99d64444"));    canvas.drawCircle(thumbX, thumbY, STROKE_WIDTH * 1.4f, thumbPaint);    thumbPaint.setColor(Color.WHITE);    canvas.drawCircle(thumbX, thumbY, STROKE_WIDTH * 0.8f, thumbPaint);  }  private boolean isDragging = false;  @Override  public boolean onTouchEvent(@NonNull MotionEvent event) {    if (!draggingEnabled) {      return super.onTouchEvent(event);    }    //处理拖动事件    float currentX = event.getX();    float currentY = event.getY();    int action = event.getAction();    switch (action) {      case MotionEvent.ACTION_DOWN:        //判断是否在进度条thumb位置        if (checkOnArc(currentX, currentY)) {          float newProgress = calDegreeByPosition(currentX, currentY) / ARC_FULL_DEGREE * max;          setProgressSync(newProgress);          isDragging = true;        }        break;      case MotionEvent.ACTION_MOVE:        if (isDragging) {          //判断拖动时是否移出去了          if (checkOnArc(currentX, currentY)) {            setProgressSync(calDegreeByPosition(currentX, currentY) / ARC_FULL_DEGREE * max);          } else {            isDragging = false;          }        }        break;      case MotionEvent.ACTION_UP:        isDragging = false;        break;    }    return true;  }  private float calDistance(float x1, float y1, float x2, float y2) {    return (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));  }  /**  * 判断该点是否在弧线上(附近)  */  private boolean checkOnArc(float currentX, float currentY) {    float distance = calDistance(currentX, currentY, centerX, centerY);    float degree = calDegreeByPosition(currentX, currentY);    return distance > circleRadius - STROKE_WIDTH * 5 && distance < circleRadius + STROKE_WIDTH * 5        && (degree >= -8 && degree <= ARC_FULL_DEGREE + 8);  }  /**  * 根据当前位置,计算出进度条已经转过的角度。  */  private float calDegreeByPosition(float currentX, float currentY) {    float a1 = (float) (Math.atan(1.0f * (centerX - currentX) / (currentY - centerY)) / Math.PI * 180);    if (currentY < centerY) {      a1 += 180;    } else if (currentY > centerY && currentX > centerX) {      a1 += 360;    }    return a1 - (360 - ARC_FULL_DEGREE) / 2;  }  public void setMax(int max) {    this.max = max;    invalidate();  }  public void setProgress(float progress) {    final float validProgress = checkProgress(progress);    //动画切换进度值    new Thread(new Runnable() {      @Override      public void run() {        float oldProgress = ProgressBarView1.this.progress;        for (int i = 1; i <= 100; i++) {          ProgressBarView1.this.progress = oldProgress + (validProgress - oldProgress) * (1.0f * i / 100);          postInvalidate();          SystemClock.sleep(20);        }      }    }).start();  }  public void setProgressSync(float progress) {    this.progress = checkProgress(progress);    invalidate();  }  //保证progress的值位于[0,max]  private float checkProgress(float progress) {    if (progress < 0) {      return 0;    }    return progress > max ? max : progress;  }  public void setDraggingEnabled(boolean draggingEnabled) {    this.draggingEnabled = draggingEnabled;  }}

(二)ProgressBarView2:

/*** 自定义绚丽的ProgressBar.*/public class ProgressBarView2 extends View {  /**  * 进度条所占用的角度  */  private static final int ARC_FULL_DEGREE = 300;  //进度条个数  private static final int COUNT = 100;  //每个进度条所占用角度  private static final float ARC_EACH_PROGRESS = ARC_FULL_DEGREE * 1.0f / (COUNT - 1);  /**  * 弧线细线条的长度  */  private int ARC_LINE_LENGTH;  /**  * 弧线细线条的宽度  */  private int ARC_LINE_WIDTH;  /**  * 组件的宽,高  */  private int width, height;  /**  * 进度条最大值和当前进度值  */  private float max, progress;  /**  * 绘制弧线的画笔  */  private Paint progressPaint;  /**  * 绘制文字的画笔  */  private Paint textPaint;  /**  * 绘制文字背景圆形的画笔  */  private Paint textBgPaint;  /**  * 圆弧的半径  */  private int circleRadius;  /**  * 圆弧圆心位置  */  private int centerX, centerY;  public ProgressBarView2(Context context) {    super(context);    init();  }  public ProgressBarView2(Context context, AttributeSet attrs) {    super(context, attrs);    init();  }  public ProgressBarView2(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);    init();  }  private void init() {    progressPaint = new Paint();    progressPaint.setAntiAlias(true);    textPaint = new Paint();    textPaint.setColor(Color.WHITE);    textPaint.setAntiAlias(true);    textBgPaint = new Paint();    textBgPaint.setAntiAlias(true);  }  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    if (width == 0 || height == 0) {      width = getWidth();      height = getHeight();      //计算圆弧半径和圆心点      circleRadius = Math.min(width, height) / 2;      ARC_LINE_LENGTH = circleRadius / 6;      ARC_LINE_WIDTH = ARC_LINE_LENGTH / 8;      centerX = width / 2;      centerY = height / 2;    }  }  private Rect textBounds = new Rect();  @Override  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    float start = (360 - ARC_FULL_DEGREE) >> 1; //进度条起始角度    float sweep1 = ARC_FULL_DEGREE * (progress / max); //进度划过的角度    //绘制进度条    progressPaint.setColor(Color.parseColor(calColor(progress / max, "#ffff0000", "#ff00ff00")));    progressPaint.setStrokeWidth(ARC_LINE_WIDTH);    float drawDegree = 1.6f;    while (drawDegree <= ARC_FULL_DEGREE) {      double a = (start + drawDegree) / 180 * Math.PI;      float lineStartX = centerX - circleRadius * (float) Math.sin(a);      float lineStartY = centerY + circleRadius * (float) Math.cos(a);      float lineStopX = lineStartX + ARC_LINE_LENGTH * (float) Math.sin(a);      float lineStopY = lineStartY - ARC_LINE_LENGTH * (float) Math.cos(a);      if (drawDegree > sweep1) {        //绘制进度条背景        progressPaint.setColor(Color.parseColor("#88aaaaaa"));        progressPaint.setStrokeWidth(ARC_LINE_WIDTH >> 1);      }      canvas.drawLine(lineStartX, lineStartY, lineStopX, lineStopY, progressPaint);      drawDegree += ARC_EACH_PROGRESS;    }    //绘制文字背景圆形    textBgPaint.setStyle(Paint.Style.FILL);//设置填充    textBgPaint.setColor(Color.parseColor("#41668b"));    canvas.drawCircle(centerX, centerY, (circleRadius - ARC_LINE_LENGTH) * 0.8f, textBgPaint);    textBgPaint.setStyle(Paint.Style.STROKE);//设置空心    textBgPaint.setStrokeWidth(2);    textBgPaint.setColor(Color.parseColor("#aaaaaaaa"));    canvas.drawCircle(centerX, centerY, (circleRadius - ARC_LINE_LENGTH) * 0.8f, textBgPaint);    //上一行文字    textPaint.setTextSize(circleRadius >> 1);    String text = (int) (100 * progress / max) + "";    float textLen = textPaint.measureText(text);    //计算文字高度    textPaint.getTextBounds("8", 0, 1, textBounds);    float h1 = textBounds.height();    canvas.drawText(text, centerX - textLen / 2, centerY - circleRadius / 10 + h1 / 2, textPaint);    //分    textPaint.setTextSize(circleRadius >> 3);    textPaint.getTextBounds("分", 0, 1, textBounds);    float h11 = textBounds.height();    canvas.drawText("分", centerX + textLen / 2 + 5, centerY - circleRadius / 10 + h1 / 2 - (h1 - h11), textPaint);    //下一行文字    textPaint.setTextSize(circleRadius / 6);    text = "点击优化";    textLen = textPaint.measureText(text);    canvas.drawText(text, centerX - textLen / 2, centerY + circleRadius / 2.5f, textPaint);  }  public void setMax(int max) {    this.max = max;    invalidate();  }  //动画切换进度值(异步)  public void setProgress(final float progress) {    new Thread(new Runnable() {      @Override      public void run() {        float oldProgress = ProgressBarView2.this.progress;        for (int i = 1; i <= 100; i++) {          ProgressBarView2.this.progress = oldProgress + (progress - oldProgress) * (1.0f * i / 100);          postInvalidate();          SystemClock.sleep(20);        }      }    }).start();  }  //直接设置进度值(同步)  public void setProgressSync(float progress) {    this.progress = progress;    invalidate();  }  /**  * 计算渐变效果中间的某个颜色值。  * 仅支持 #aarrggbb 模式,例如 #ccc9c9b2  */  public String calColor(float fraction, String startValue, String endValue) {    int start_a, start_r, start_g, start_b;    int end_a, end_r, end_g, end_b;    //start    start_a = getIntValue(startValue, 1, 3);    start_r = getIntValue(startValue, 3, 5);    start_g = getIntValue(startValue, 5, 7);    start_b = getIntValue(startValue, 7, 9);    //end    end_a = getIntValue(endValue, 1, 3);    end_r = getIntValue(endValue, 3, 5);    end_g = getIntValue(endValue, 5, 7);    end_b = getIntValue(endValue, 7, 9);    return "#" + getHexString((int) (start_a + fraction * (end_a - start_a)))        + getHexString((int) (start_r + fraction * (end_r - start_r)))        + getHexString((int) (start_g + fraction * (end_g - start_g)))        + getHexString((int) (start_b + fraction * (end_b - start_b)));  }  //从原始#AARRGGBB颜色值中指定位置截取,并转为int.  private int getIntValue(String hexValue, int start, int end) {    return Integer.parseInt(hexValue.substring(start, end), 16);  }  private String getHexString(int value) {    String a = Integer.toHexString(value);    if (a.length() == 1) {      a = "0" + a;    }    return a;  }}




更多相关文章

  1. Android(安卓)GridView 方格中图标与文字如何同时存在
  2. 彻底理解Android沉浸状态栏适配
  3. 使用h5+下载并打开文件,支持Android,IOS
  4. 设置进度条的样式
  5. Android(安卓)三种方式实现自定义圆形页面加载中效果的进度条
  6. 【转载】自定义圆形进度条ProgressBar的三种方式
  7. android 数字进度条--NumberProgressBar
  8. Android(安卓)TextView中部分文字高亮,且可响应点击事件
  9. android之requestWindowFeature详解

随机推荐

  1. Android小问题:android studio怎么查看数
  2. LayoutInflater使用
  3. Android(安卓)scrollview嵌套listview出
  4. Andorid TabHost 使用小结
  5. android 平台开机自动重启
  6. 【Android学习笔记1】Android(安卓)Studi
  7. android基础6——设置圆角按钮
  8. 从setContentView说起
  9. Android启动过程 && Activity的生命周期
  10. Android(安卓)开发 短信app