Android自定义View圆形进度条控件(三)
程序员文章站
2023-11-17 12:46:04
继续练习自定义view,这次带来的圆形进度条控件与之前的圆形百分比控件大同小异,这次涉及到了渐变渲染以及画布旋转等知识点,效果如下:
虽然步骤类似,但是我还是要写,毕...
继续练习自定义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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。