当前位置: 移动技术网 > 移动技术>移动开发>Android > Android自定义控件实现带文本与数字的圆形进度条

Android自定义控件实现带文本与数字的圆形进度条

2019年07月30日  | 移动技术网移动技术  | 我要评论

本文实例为大家分享了android实现圆形进度条的具体代码,供大家参考,具体内容如下

实现的效果图如下所示:

第一步:绘制下方有缺口的空心圆,称为外围大弧吧

anvas.cliprect(0, 0, mwidth, mheight / 2 + radius - textheight * 3 / 4);

第二步:计算绘制圆弧进度条时的起始角度,设置为外围大弧的左端点为进度值得起点,扫过的角度所占外围大弧的百分比就是进度值

第三步:绘制数字、文字、百分号

第四步:使用handler runnable 和decelerateinterpolator是进度条和数字动起来

测试代码:

final customcirclebar circle=(customcirclebar)findviewbyid(r.id.win_home);
circle.setpercent(10);
circle.setcustomtext("呵呵");
circle.setprogesscolor(getresources().getcolor(r.color.blue));
final random random=new random();
circle.setonclicklistener(new view.onclicklistener(){
 @override
 public void onclick(view v){
 circle.setpercent(random.nextint(100));
 }
});

完成代码如下:

public class customcirclebar extends view {
 private context context;
 /**
 * 进度值
 */
 private int percent;
 /**
 * 颜色值
 */
 private int mprogesscolor;
 /**
 * 下边的文字名称
 */
 private string mcustomtext;
 /**
 * 外圈圆环的画笔
 */
 private paint paintbar = new paint();
 /**
 * 下边文字的画笔
 */
 private paint painttext = new paint();
 /**
 * 动态获取属性值
 */
 private typedvalue typedvalue;
 /**
 * 先加速后减速
 */
 decelerateinterpolator mdecelerateinterpolator = new decelerateinterpolator();
 /**
 * 动画持续时间
 */
 private int duration = 10;
 private int curtime = 0;
 public customcirclebar(context context) {
 super(context);
 this.context=context;
 init();
 }
 
 public customcirclebar(context context, attributeset attrs) {
 super(context, attrs);
 this.context=context;
 init();
 }
 
 public customcirclebar(context context, attributeset attrs, int defstyleattr) {
 super(context, attrs, defstyleattr);
 this.context=context;
 init();
 }
 
 
 
 public void setpercent(int percent) {
 this.percent = percent;
 /*isshown():returns the visibility of this view and all of its ancestors*/
 if (isshown()) {
  /**
  * 设置进度后重新开始一次动画
  */
  curtime=0;
  this.invalidate();
 }
 }
 
 public void setprogesscolor(int mprogesscolor) {
 this.mprogesscolor = mprogesscolor;
 if (isshown()) {
  this.invalidate();
 }
 }
 
 
 public void setcustomtext(string mcustomtext) {
 this.mcustomtext = mcustomtext;
 }
 
 private handler mhandler = new handler();
 private runnable manimation = new runnable() {
 @override
 public void run() {
  if (curtime < duration) {
  curtime++;
  /** 导致重绘,调用ondraw,ondraw最后调用
   * mhandler.postdelayed(manimation, 20);更新进度条,界面重绘
   * 每次20毫秒,绘制10次,因此动画时间200毫秒
   */
  customcirclebar.this.invalidate();
  }
 }
 };
 
 private void init() {
 /**
  * 数据初始化,没有设置属性时候的默认值
  */
 percent = 0;
 mprogesscolor=color.rgb(95,112,72);
 mcustomtext="home";
 typedvalue=new typedvalue();
 context.gettheme().resolveattribute(r.attr.maintextclor,typedvalue,true);
 }
 
 
 
 @override
 protected void ondraw(canvas canvas) {
 super.ondraw(canvas);
 float mwidth = getwidth();
 float mheight = getheight();
 /**
  * 下边是进度条画笔的设置
  */
 /** restores the paint to its default settings. */
 paintbar.reset();
 /**
  * 圆环宽度4个像素
  */
 paintbar.setstrokewidth(4);
 /**
  * 空心圆环而非填充的额扇形
  */
 paintbar.setstyle(paint.style.stroke);
 paintbar.setantialias(true);
 paintbar.setcolor(mprogesscolor);
 /**
  * 调整下不透明度,使边框弧和进度条区分开
  */
 paintbar.setalpha(80);
 /**
  * 接下来是文字画笔的设置
  */
 painttext.settextsize(20);
 painttext.setcolor(getresources().getcolor(typedvalue.resourceid));
 painttext.setstyle(paint.style.stroke);
 painttext.setantialias(true);
 /**
  * 从中间开始绘制文本
  */
 painttext.settextalign(paint.align.center);
 /**
  * 测量文字大小
  */
 paint.fontmetrics fontmetrics = painttext.getfontmetrics();
 /**
  * 计算文字高度
  */
 float textheight = fontmetrics.bottom - fontmetrics.top;
 /**
  * 计算圆的半径
  */
 float radius = math.min(mwidth, mheight) / 2 - 10;
 /* ❑ save:用来保存canvas的状态。save之后,可以调用canvas的平移、放缩、旋转、错切、裁剪等操作。
  ❑ restore:用来恢复canvas之前保存的状态。防止save后对canvas执行的操作对后续的绘制有影响。*/
 /*保存画布,绘制进度条*/
 canvas.save();
 /*cliprect:该方法用于裁剪画布,也就是设置画布的显示区域
 调用cliprect()方法后,只会显示被裁剪的区域,之外的区域将不会显示 */
 canvas.cliprect(0, 0, mwidth, mheight / 2 + radius - textheight * 3 / 4);
 /*因为cliprect的原因,外边的圆环下边留个缺口绘制文字*/
 canvas.drawcircle(mwidth / 2, mheight / 2, radius, paintbar);
 
 /**
  * 三角函数计算,下方缺口扇形的角度的一半
  */
 float theta_offset = (float) math.acos((radius - textheight / 2) / radius);
 /**
  * 大弧围成的扇形的角度
  */
 float theta_full = 360 - 2 * theta_offset;
 /**
  * 进度值围成的弧对应的角度
  */
 float thetaprocess = mdecelerateinterpolator.getinterpolation(1.0f * curtime / duration) * percent * theta_full / 100;
 /**
  * 设置进度值颜色完全不透明
  */
 paintbar.setalpha(255);
 paintbar.setcolor(mprogesscolor);
 /**
  * 注意弧形的起始角度,下边因显示文字导致圆环断开成一条弧,弧有左右两个端点,从左端点开始画弧
  */
 canvas.drawarc(new rectf(mwidth / 2 - radius, mheight / 2 - radius, mwidth / 2 + radius, mheight / 2 + radius), theta_offset+90, thetaprocess, false, paintbar);
 /**
  * 恢复画布
  */
 canvas.restore();
 /**
  * 开始绘制文字
  */
 painttext.settextsize(20);
 fontmetrics = painttext.getfontmetrics();
 float textbaselineoffset = (fontmetrics.bottom - fontmetrics.top) / 2 - fontmetrics.bottom;
 canvas.drawtext(mcustomtext, mwidth / 2, mheight / 2 + radius - textheight / 2 + textbaselineoffset, painttext);
 
 /**
  * 绘制百分号
  */
 painttext.settextsize(mheight * 1 / 8);
 fontmetrics = painttext.getfontmetrics();
 textbaselineoffset = (fontmetrics.bottom - fontmetrics.top) / 2 - fontmetrics.bottom;
 canvas.drawtext("%", mwidth / 2, mheight / 2 + radius / 3 + textbaselineoffset, painttext);
 
 /**
  * 绘制百分比
  */
 painttext.settextsize(mheight * 3 / 8);
 canvas.drawtext("" + (int)(percent*mdecelerateinterpolator.getinterpolation(1.0f * curtime / duration)), mwidth / 2, mheight / 2, painttext);
 /**
  * 20毫秒后执行动画
  */
 mhandler.postdelayed(manimation, 20);
 }
}

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网