当前位置: 移动技术网 > IT编程>移动开发>Android > Android编程基于自定义View实现绚丽的圆形进度条功能示例

Android编程基于自定义View实现绚丽的圆形进度条功能示例

2019年07月24日  | 移动技术网IT编程  | 我要评论

魔门之异界至尊txt下载,有关端午节的手抄报,心情冲浪

本文实例讲述了android编程基于自定义view实现绚丽的圆形进度条功能。分享给大家供大家参考,具体如下:

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

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

更多关于android相关内容感兴趣的读者可查看本站专题:《android视图view技巧总结》、《android开发动画技巧汇总》、《android编程之activity操作技巧总结》、《android布局layout技巧总结》、《android开发入门与进阶教程》、《android资源操作技巧汇总》及《android控件用法总结

希望本文所述对大家android程序设计有所帮助。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网