Android自定义View圆形百分比控件(一)
程序员文章站
2023-11-21 10:50:10
做一个自定义view的小练习,效果如下
只需要画一个圆、一个圆弧、一个百分比文本,添加一个点击事件,传入百分比重绘
1、在res/values文件夹下新建attrs...
做一个自定义view的小练习,效果如下
只需要画一个圆、一个圆弧、一个百分比文本,添加一个点击事件,传入百分比重绘
1、在res/values文件夹下新建attrs.xml文件,编写自定义属性:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="circlepercentview" > <attr name="circlebg" format="color"/> <attr name="arccolor" format="color"/> <attr name="arcwidth" format="dimension"/> <attr name="percenttextcolor" format="color"/> <attr name="percenttextsize" format="dimension"/> <attr name="radius" format="dimension"/> </declare-styleable> </resources>
2、新建circlepercentview继承view,重写构造方法:
public circlepercentview(context context) { this(context, null); } public circlepercentview(context context, attributeset attrs) { this(context, attrs, 0); } public circlepercentview(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); }
3、在第三个构造方法中获取自定义属性的值:
typedarray ta = context.obtainstyledattributes(attrs, r.styleable.circlepercentview, defstyleattr, 0); mcirclecolor = ta.getcolor(r.styleable.circlepercentview_circlebg, 0xff8e29fa); marccolor = ta.getcolor(r.styleable.circlepercentview_arccolor, 0xffffee00); marcwidth = ta.getdimensionpixelsize(r.styleable.circlepercentview_arcwidth, densityutils.dp2px(context, 16)); mpercenttextcolor = ta.getcolor(r.styleable.circlepercentview_arccolor, 0xffffee00); mpercenttextsize = ta.getdimensionpixelsize(r.styleable.circlepercentview_percenttextsize, densityutils.sp2px(context, 16)); mradius = ta.getdimensionpixelsize(r.styleable.circlepercentview_radius, densityutils.dp2px(context, 100)); ta.recycle();
4、创建画图所使用的对象,如paint、rect、rectf:
mcirclepaint = new paint(paint.anti_alias_flag); mcirclepaint.setstyle(paint.style.fill); mcirclepaint.setcolor(mcirclecolor); marcpaint = new paint(paint.anti_alias_flag); marcpaint.setstyle(paint.style.stroke); marcpaint.setstrokewidth(marcwidth); marcpaint.setcolor(marccolor); marcpaint.setstrokecap(paint.cap.round);//使圆弧两头圆滑 mpercenttextpaint = new paint(paint.anti_alias_flag); mpercenttextpaint.setstyle(paint.style.stroke); mpercenttextpaint.setcolor(mpercenttextcolor); mpercenttextpaint.settextsize(mpercenttextsize); marcrectf = new rectf();//圆弧的外接矩形 mtextbound = new rect();//文本的范围矩形
5、重写onmeasure()方法,计算自定义view的宽高:
@override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { setmeasureddimension(measuredimension(widthmeasurespec), measuredimension(heightmeasurespec)); } private int measuredimension(int measurespec) { int result; int specmode = measurespec.getmode(measurespec); int specsize = measurespec.getsize(measurespec); if (specmode == measurespec.exactly) {//精确地,代表宽高为定值或者match_parent时 result = specsize; } else { result = 2 * mradius; if (specmode == measurespec.at_most) {//最大地,代表宽高为wrap_content时 result = math.min(result, specsize); } } return result; }
6、重写ondraw()方法,绘制圆、圆弧和百分比文本,注意坐标的计算:
@override protected void ondraw(canvas canvas) { //画圆 canvas.drawcircle(getwidth() / 2, getheight() / 2, mradius, mcirclepaint); //画圆弧 marcrectf.set(getwidth() / 2 - mradius + marcwidth / 2, getheight() / 2 - mradius + marcwidth / 2 , getwidth() / 2 + mradius - marcwidth / 2, getheight() / 2 + mradius - marcwidth / 2); canvas.drawarc(marcrectf, 270, 360 * mcurpercent / 100, false, marcpaint); string text = mcurpercent + "%"; //计算文本宽高 mpercenttextpaint.gettextbounds(text, 0, string.valueof(text).length(), mtextbound); //画百分比文本 canvas.drawtext(text, getwidth() / 2 - mtextbound.width() / 2 , getheight() / 2 + mtextbound.height() / 2, mpercenttextpaint); }
7、给这个view设置点击事件,暴露一个动态设置百分比的方法:
public void setcurpercent(float curpercent) { valueanimator anim = valueanimator.offloat(mcurpercent, curpercent); //动画时长由百分比大小决定 anim.setduration((long) (math.abs(mcurpercent - curpercent) * 20)); anim.addupdatelistener(new valueanimator.animatorupdatelistener() { @override public void onanimationupdate(valueanimator animation) { float value = (float) animation.getanimatedvalue(); mcurpercent = (float) (math.round(value * 10)) / 10;//四舍五入保留到小数点后两位 invalidate();//重绘,重走ondraw()方法,这也是不能再ondraw()中创建对象的原因 } }); anim.start(); } public void setoncircleclicklistener(onclicklistener onclicklistener) { this.monclicklistener = onclicklistener; } //在构造方法中 setonclicklistener(new onclicklistener() { @override public void onclick(view v) { if (monclicklistener != null) { monclicklistener.onclick(circlepercentview.this); } } });
8、在activity_main.xml布局文件中使用该view:
<!-- 使用自定义命名空间namespace,cpv是该控件名的首字母缩写,可以随意取 --> <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cpv="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- cpv后面的属性名对应attrs.xml文件中的自定义属性名 --> <com.monkey.customviewdemo.view.circlepercentview android:id="@+id/circlepercentview" android:layout_width="match_parent" android:layout_height="match_parent" cpv:arccolor="#ffee00" cpv:arcwidth="@dimen/activity_horizontal_margin" cpv:circlebg="#8e29fa" cpv:percenttextcolor="#ffee00" cpv:percenttextsize="16sp" cpv:radius="100dp" /> </relativelayout>
9、在mainactivity.java中设置监听,传入百分比:
mcirclepercentview = (circlepercentview) findviewbyid(r.id.circlepercentview); mcirclepercentview.setoncircleclicklistener(new view.onclicklistener() { @override public void onclick(view v) { float percent = (float) (math.random() * 99 + 1); mcirclepercentview.setcurpercent(percent); } });
代码下载地址:
https://github.com/monkeymushroom/circlepercentview/tree/master
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。