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

Android自定义View圆形进度条控件(三)

程序员文章站 2023-11-17 12:46:04
继续练习自定义view,这次带来的圆形进度条控件与之前的圆形百分比控件大同小异,这次涉及到了渐变渲染以及画布旋转等知识点,效果如下: 虽然步骤类似,但是我还是要写,毕...

继续练习自定义view,这次带来的圆形进度条控件与之前的圆形百分比控件大同小异,这次涉及到了渐变渲染以及画布旋转等知识点,效果如下:

Android自定义View圆形进度条控件(三)

虽然步骤类似,但是我还是要写,毕竟基础的东西就是要多练

1、在res/values文件夹下新建attrs.xml文件,编写自定义属性:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="circleprogressview">
 <!-- 弧线宽度 -->
 <attr name="arcwidth" format="dimension" />
 <!-- 刻度个数 -->
 <attr name="scalecount" format="integer" />
 <!-- 渐变起始颜色 -->
 <attr name="startcolor" format="color" />
 <!-- 渐变终止颜色 -->
 <attr name="endcolor" format="color" />
 <!-- 标签说明文本 -->
 <attr name="labeltext" format="string" />
 <!-- 文本颜色 -->
 <attr name="textcolor" format="color" />
 <!-- 百分比文本字体大小 -->
 <attr name="progresstextsize" format="dimension" />
 <!-- 标签说明字体大小 -->
 <attr name="labeltextsize" format="dimension" />
 </declare-styleable>
</resources>

2、新建circleprogressview继承view,重写构造方法:

 public circleprogressview(context context) {
 this(context, null);
 }

 public circleprogressview(context context, attributeset attrs) {
 this(context, attrs, 0);
 }

 public circleprogressview(context context, attributeset attrs, int defstyleattr) {
 super(context, attrs, defstyleattr);
 }

3、在第三个构造方法中获取自定义属性的值:

 typedarray ta = context.obtainstyledattributes(attrs, r.styleable.circleprogressview, defstyleattr, 0);
 marcwidth = ta.getdimension(r.styleable.circleprogressview_arcwidth, densityutils.dp2px(context, 8));
 mscalecount = ta.getinteger(r.styleable.circleprogressview_scalecount, 24);
 mstartcolor = ta.getcolor(r.styleable.circleprogressview_startcolor, color.parsecolor("#3fc199"));
 mendcolor = ta.getcolor(r.styleable.circleprogressview_endcolor, color.parsecolor("#3294c1"));
 mcolorarray = new int[]{mstartcolor, mendcolor};
 mlabeltext = ta.getstring(r.styleable.circleprogressview_labeltext);
 mtextcolor = ta.getcolor(r.styleable.circleprogressview_textcolor, color.parsecolor("#4f5f6f"));
 mprogresstextsize = ta.getdimension(r.styleable.circleprogressview_progresstextsize, 160);
 mlabeltextsize = ta.getdimension(r.styleable.circleprogressview_labeltextsize, 64);
 ta.recycle();

4、创建画图所使用的对象,如paint、rect、rectf:

 marcbackpaint = new paint(paint.anti_alias_flag);
 marcbackpaint.setstyle(paint.style.stroke);
 marcbackpaint.setstrokewidth(marcwidth);
 marcbackpaint.setcolor(color.ltgray);

 marcforepaint = new paint(paint.anti_alias_flag);
 marcforepaint.setstyle(paint.style.stroke);
 marcforepaint.setstrokewidth(marcwidth);

 marcrectf = new rectf();

 mlinepaint = new paint(paint.anti_alias_flag);
 mlinepaint.setstyle(paint.style.stroke);
 mlinepaint.setcolor(color.white);
 mlinepaint.setstrokewidth(densityutils.dp2px(context, 2));

 mprogresstextpaint = new paint(paint.anti_alias_flag);
 mprogresstextpaint.setstyle(paint.style.fill);
 mprogresstextpaint.setcolor(mtextcolor);
 mprogresstextpaint.settextsize(mprogresstextsize);

 mlabeltextpaint = new paint(paint.anti_alias_flag);
 mlabeltextpaint.setstyle(paint.style.fill);
 mlabeltextpaint.setcolor(mtextcolor);
 mlabeltextpaint.settextsize(mlabeltextsize);

 mtextrect = new rect();

5、重写onmeasure()方法,计算自定义view的宽高:

 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
 setmeasureddimension(measureddimension(widthmeasurespec), measureddimension(heightmeasurespec));
 }

 private int measureddimension(int measurespec) {
 int result;
 int mode = measurespec.getmode(measurespec);
 int size = measurespec.getsize(measurespec);
 if (mode == measurespec.exactly) {
  result = size;
 } else {
  result = 800;
  if (mode == measurespec.at_most) {
  result = math.min(result, size);
  }
 }
 return result;
 }

6、重写ondraw()方法,绘制圆弧、刻度线和百分比文本、标签说明文本,注意坐标的计算:

 @override
 protected void ondraw(canvas canvas) {
 super.ondraw(canvas);
 marcrectf.set(marcwidth / 2, marcwidth / 2, getwidth() - marcwidth / 2, getheight() - marcwidth / 2);
 //画背景弧线
 canvas.drawarc(marcrectf, -90, 360, false, marcbackpaint);
 //设置渐变渲染
 lineargradient lineargradient = new lineargradient(getwidth() / 2, 0, getwidth() / 2, getheight(), mcolorarray, null, shader.tilemode.clamp);
 marcforepaint.setshader(lineargradient);
 //画百分比值弧线
 canvas.drawarc(marcrectf, -90, msweepangle, false, marcforepaint);
 //画刻度线
 for (int i = 0; i < mscalecount; i++) {
  canvas.drawline(getwidth() / 2, 0, getwidth() / 2, marcwidth, mlinepaint);
  //旋转画布
  canvas.rotate(360 / mscalecount, getwidth() / 2, getheight() / 2);
 }
 //画百分比文本
 string progresstext = mprogress + "%";
 mprogresstextpaint.gettextbounds(progresstext, 0, progresstext.length(), mtextrect);
 float progresstextwidth = mtextrect.width();
 float progresstextheight = mtextrect.height();
 canvas.drawtext(progresstext, getwidth() / 2 - progresstextwidth / 2,
  getheight() / 2 + progresstextheight / 2, mprogresstextpaint);
 //画标签说明文本
 mlabeltextpaint.gettextbounds(mlabeltext, 0, mlabeltext.length(), mtextrect);
 canvas.drawtext(mlabeltext, getwidth() / 2 - mtextrect.width() / 2,
  getheight() / 2 - progresstextheight / 2 - mtextrect.height(), mlabeltextpaint);
 }

7、暴露一个动态设置百分比的方法:

 public void setprogress(float progress) {
 log.e("--> ", progress + "");
 valueanimator anim = valueanimator.offloat(mprogress, progress);
 anim.setduration((long) (math.abs(mprogress - progress) * 20));
 anim.addupdatelistener(new valueanimator.animatorupdatelistener() {
  @override
  public void onanimationupdate(valueanimator animation) {
  mprogress = (float) animation.getanimatedvalue();
  msweepangle = mprogress * 360 / 100;
  mprogress = (float) (math.round(mprogress * 10)) / 10;//四舍五入保留到小数点后两位
  invalidate();
  }
 });
 anim.start();
 }

8、在activity_main.xml布局文件中使用该view:

<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:cpv="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:paddingbottom="@dimen/activity_vertical_margin"
 android:paddingleft="@dimen/activity_horizontal_margin"
 android:paddingright="@dimen/activity_horizontal_margin"
 android:paddingtop="@dimen/activity_vertical_margin"
 tools:context=".mainactivity">

 <com.monkey.circleprogressview.circleprogressview
 android:id="@+id/circle_progress_view"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_centerinparent="true"
 cpv:arcwidth="8dp"
 cpv:endcolor="#126b94"
 cpv:labeltext="学习进度"
 cpv:labeltextsize="20sp"
 cpv:progresstextsize="55sp"
 cpv:scalecount="24"
 cpv:startcolor="#12d699"
 cpv:textcolor="#4f5f6f" />
</relativelayout>

9、在mainactivity中设置监听,传入百分比:

 final circleprogressview view = (circleprogressview) findviewbyid(r.id.circle_progress_view);
 view.setonclicklistener(new view.onclicklistener() {
 @override
 public void onclick(view v) {
  float progress = (float) (math.random() * 100);
  view.setprogress(progress);
 }
 });

代码下载地址:
https://github.com/monkeymushroom/circleprogressview/tree/master

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