欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现带数字的圆形进度条(自定义进度条)

程序员文章站 2023-12-19 18:29:46
开发 设计搞了一个带圆形进度的进度条,在github上逛了一圈,发现没有,自己撸吧。 先看界面效果: 主要思路是写一个继承progressbar的自定义view,...

开发

设计搞了一个带圆形进度的进度条,在github上逛了一圈,发现没有,自己撸吧。

先看界面效果:

Android实现带数字的圆形进度条(自定义进度条)

主要思路是写一个继承progressbar的自定义view,不废话,直接上代码:

package com.fun.progressbarwithnumber;
import android.content.context;
import android.content.res.typedarray;
import android.graphics.canvas;
import android.graphics.paint;
import android.graphics.rectf;
import android.util.attributeset;
import android.util.typedvalue;
import android.widget.progressbar;
public class horizontalprogressbarwithnumber extends progressbar {
  private static final int default_text_size = 10;
  private static final int default_text_color = 0xfffc00d1;
  private static final int default_color_unreached_color = 0xffd3d6da;
  private static final int default_height_reached_progress_bar = 2;
  private static final int default_height_unreached_progress_bar = 2;
  private static final int default_circle_color = 0xff3f51b5;
  protected paint mpaint = new paint();
  // 字体颜色
  protected int mtextcolor = default_text_color;
  // 字体大小
  protected int mtextsize = sp2px(default_text_size);
  // 覆盖进度高度
  protected int mreachedprogressbarheight = dp2px(default_height_reached_progress_bar);
  // 覆盖进度颜色
  protected int mreachedbarcolor = default_text_color;
  // 未覆盖进度高度
  protected int munreachedprogressbarheight = dp2px(default_height_unreached_progress_bar);
  // 未覆盖进度颜色
  protected int munreachedbarcolor = default_color_unreached_color;
  // 圆的颜色
  protected int mcirclecolor = default_circle_color;
  protected int mrealwidth;
  protected boolean mifdrawtext = true;
  protected boolean mifdrawcircle = true;
  protected static final int visible = 0;
  public horizontalprogressbarwithnumber(context context, attributeset attrs) {
    this(context, attrs, 0);
  }
  public horizontalprogressbarwithnumber(context context, attributeset attrs, int defstyle) {
    super(context, attrs, defstyle);
    obtainstyledattributes(attrs);
    mpaint.settextsize(mtextsize);
    mpaint.setcolor(mtextcolor);
    mpaint.setantialias(true);
  }
  private void obtainstyledattributes(attributeset attrs) {
    // 获取自定义属性
    final typedarray attributes = getcontext().obtainstyledattributes(attrs, r.styleable.horizontalprogressbarwithnumber);
    mtextcolor = attributes.getcolor(r.styleable.horizontalprogressbarwithnumber_progress_text_color, default_text_color);
    mtextsize = (int) attributes.getdimension(r.styleable.horizontalprogressbarwithnumber_progress_text_size, mtextsize);
    mcirclecolor = attributes.getcolor(r.styleable.horizontalprogressbarwithnumber_progress_circle_color, default_circle_color);
    mreachedbarcolor = attributes.getcolor(r.styleable.horizontalprogressbarwithnumber_progress_reached_color, mtextcolor);
    munreachedbarcolor = attributes.getcolor(r.styleable.horizontalprogressbarwithnumber_progress_unreached_color, default_color_unreached_color);
    mreachedprogressbarheight = (int) attributes.getdimension(r.styleable.horizontalprogressbarwithnumber_progress_reached_bar_height, mreachedprogressbarheight);
    munreachedprogressbarheight = (int) attributes.getdimension(r.styleable.horizontalprogressbarwithnumber_progress_unreached_bar_height, munreachedprogressbarheight);
    int textvisible = attributes.getint(r.styleable.horizontalprogressbarwithnumber_progress_text_visibility, visible);
    if (textvisible != visible) {
      mifdrawtext = false;
    }
    attributes.recycle();
    int left = (int) (mreachedprogressbarheight * 0.8), right = (int) (mreachedprogressbarheight * 0.8);
    int top = (int) (mreachedprogressbarheight * 0.3 + dp2px(1)), bottom = (int) (mreachedprogressbarheight * 0.3 + dp2px(1));
    setpadding(left, top, right, bottom);
  }
  @override
  protected synchronized void onmeasure(int widthmeasurespec, int heightmeasurespec) {
    int width = measurespec.getsize(widthmeasurespec);
    int height = measureheight(heightmeasurespec);
    setmeasureddimension(width, height);
    mrealwidth = getmeasuredwidth() - getpaddingright() - getpaddingleft();
  }
  private int measureheight(int measurespec) {
    int result;
    int specmode = measurespec.getmode(measurespec);
    int specsize = measurespec.getsize(measurespec);
    if (specmode == measurespec.exactly) {
      result = specsize;
    } else {
      float textheight = (mpaint.descent() - mpaint.ascent());
      result = (int) (getpaddingtop() + getpaddingbottom() + math.max(
          math.max(mreachedprogressbarheight, munreachedprogressbarheight), math.abs(textheight)));
      if (specmode == measurespec.at_most) {
        result = math.min(result, specsize);
      }
    }
    return result;
  }
  @override
  protected synchronized void ondraw(canvas canvas) {
    canvas.save();
    canvas.translate(getpaddingleft(), getheight() / 2);
    boolean noneedbg = false;
    float radio = getprogress() * 1.0f / getmax();
    float progressposx = (int) (mrealwidth * radio);
    string text = getprogress() + "%";
    float textwidth = mpaint.measuretext(text);
    float textheight = (mpaint.descent() + mpaint.ascent()) / 2;
    float radius = (mreachedprogressbarheight + getpaddingbottom() + getpaddingtop()) / 2;
    // 覆盖的进度
    float endx = progressposx;
    if (endx > -1) {
      mpaint.setcolor(mreachedbarcolor);
      rectf rectf = new rectf(0, 0 - getpaddingtop() - getpaddingbottom(),
          endx, mreachedprogressbarheight - getpaddingbottom());
      canvas.drawroundrect(rectf, 25, 25, mpaint);
    }
    // 未覆盖的进度
    if (!noneedbg) {
      float start = progressposx;
      mpaint.setcolor(munreachedbarcolor);
      rectf rectf = new rectf(start, 0 - getpaddingtop() - getpaddingbottom(),
          mrealwidth + getpaddingright() - radius, mreachedprogressbarheight - getpaddingbottom());
      canvas.drawroundrect(rectf, 25, 25, mpaint);
    }
    // 圆
    if (mifdrawcircle) {
      mpaint.setcolor(mcirclecolor);
      canvas.drawcircle(progressposx, 0, radius, mpaint);
    }
    // 文本
    if (mifdrawtext) {
      mpaint.setcolor(mtextcolor);
      canvas.drawtext(text, progressposx - textwidth / 2, -textheight, mpaint);
    }
    canvas.restore();
  }
  /**
   * dp 2 px
   */
  protected int dp2px(int dpval) {
    return (int) typedvalue.applydimension(typedvalue.complex_unit_dip, dpval, getresources().getdisplaymetrics());
  }
  /**
   * sp 2 px
   */
  protected int sp2px(int spval) {
    return (int) typedvalue.applydimension(typedvalue.complex_unit_sp, spval, getresources().getdisplaymetrics());
  }
}

使用

在布局文件中加入:

<com.fun.progressbarwithnumber.horizontalprogressbarwithnumber
    android:id="@+id/hpbwn"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    fun:progress_circle_color="#ff000000"
    fun:progress_reached_bar_height="20dp"
    fun:progress_reached_color="#ffff4081"
    fun:progress_text_color="#ffffffff"
    fun:progress_text_size="14sp"
    fun:progress_unreached_bar_height="20dp"
    fun:progress_unreached_color="#ffbcb4e8" />

progress_reached_bar_height:当前进度的高度
progress_unreached_bar_height:剩余进度的高度
progress_text_size:圆圈内文字的大小

注意:

当前进度和剩余进度的高度要一致,圆圈大小和圆圈内文字的大小要配合java代码调整。

项目源码:

https://github.com/hfrommane/progressbarwithnumber

以上所述是小编给大家介绍的android实现带数字的圆形进度条(自定义进度条),希望对大家有所帮助

上一篇:

下一篇: