Android自定义环形LoadingView效果
程序员文章站
2023-08-25 13:58:15
最近项目有要用到环形的进度条,github上有一个类似的dashedcircularprogress控件,但是他画的进度是通过设置画笔的虚线效果来实现间隔的:progres...
最近项目有要用到环形的进度条,github上有一个类似的dashedcircularprogress控件,但是他画的进度是通过设置画笔的虚线效果来实现间隔的:progresspaint.setpatheffect(new dashpatheffect(new float[]{dashwith, dashspace}, dashspace));如果内层还有一层圆环,在动态设置时,内层和外层有细微的偏差.于是我在原有基础上改了一个,实现了我要的效果(设置进度时可以选择加动画或者不加动画):
控件实现:
这个控件继承relativelayout,在ondraw时做了两件事:
1、先画出底部的黑色环形;
2、按照当时的进度值画出对应比例的外层绿色环形.
对外提供一个接口,回调当前进度值:
public interface onvaluechangelistener { void onvaluechange(float value); }
核心绘制类:
internalcirclepainterimp2,绘制内层的黑色的环形:
/** * @author chuck */ public class internalcirclepainterimp2 implements internalcirclepainter { private rectf internalcircle;//画出圆弧时,圆弧的外切矩形 private paint internalcirclepaint; private int color; private float startangle = 270f; int arcquantity=100;//等分(圆弧加间隔),比如arcquantity=100时,表示将有100个圆弧,和100个空白间隔 float ratio=0.5f;//每段圆弧与圆弧加间隔之和的比例,ratio=0.5表示每个圆弧与相邻的间隔弧度比是1:1 private int width; private int height; private int internalstrokewidth = 48;//圆环宽度 public internalcirclepainterimp2(int color, int progressstrokewidth, int arcquantity,float ratio) { this.color = color; this.internalstrokewidth = progressstrokewidth; this.arcquantity = arcquantity; if(ratio>0&&ratio<1){ this.ratio = ratio; } init(); } private void init() { initexternalcirclepainter(); } private void initexternalcirclepainter() { internalcirclepaint = new paint(); internalcirclepaint.setantialias(true); internalcirclepaint.setstrokewidth(internalstrokewidth); internalcirclepaint.setcolor(color); internalcirclepaint.setstyle(paint.style.stroke); } //圆弧外切矩形 private void initexternalcircle() { internalcircle = new rectf(); float padding = internalstrokewidth * 0.5f; internalcircle.set(padding, padding , width - padding, height - padding); initexternalcirclepainter(); } @override public void draw(canvas canvas) { float eachangle=360f/arcquantity; float eacharcangle=eachangle*ratio; for(int i=0;i<arcquantity*2;i++){ if(i%2==0){//遇到偶数就画圆弧,基数则跳过 canvas.drawarc(internalcircle, startangle+eachangle*i/2, eacharcangle, false, internalcirclepaint); } else{ continue; } } } public void setcolor(int color) { this.color = color; internalcirclepaint.setcolor(color); } @override public int getcolor() { return color; } @override public void onsizechanged(int height, int width) { this.width = width; this.height = height; initexternalcircle(); } }
progresspainterimp2,绘制内层的黑色的环形:
/** * @author chuck */ public class progresspainterimp2 implements progresspainter { private rectf progresscircle; private paint progresspaint; private int color = color.red; private float startangle = 270f; private int internalstrokewidth = 48; private float min; private float max; private int width; private int height; private int currentpecent;//当前的百分比 int arcquantity=100;//等分(圆弧加间隔),比如arcquantity=100时,表示将有100个圆弧,和100个空白间隔 float ratio=0.5f;//每段圆弧与圆弧加间隔之和的比例,ratio=0.5表示每个圆弧与相邻的间隔弧度比是1:1 public progresspainterimp2(int color, float min, float max, int progressstrokewidth, int arcquantity,float ratio) { this.color = color; this.min = min; this.max = max; this.internalstrokewidth = progressstrokewidth; this.arcquantity = arcquantity; this.ratio = ratio; init(); log.e("progresspainterimp","构造函数执行"); } private void init() { initinternalcirclepainter(); } private void initinternalcirclepainter() { progresspaint = new paint(); progresspaint.setantialias(true); progresspaint.setstrokewidth(internalstrokewidth); progresspaint.setcolor(color); progresspaint.setstyle(paint.style.stroke); } //初始化外切的那个矩形 private void initinternalcircle() { progresscircle = new rectf(); float padding = internalstrokewidth * 0.5f; progresscircle.set(padding, padding , width - padding, height - padding); initinternalcirclepainter(); } @override public void draw(canvas canvas) { float eachangle=360f/arcquantity; float eacharcangle=eachangle*ratio; int quantity=2*arcquantity*currentpecent/100; for(int i=0;i<quantity;i++){ if(i%2==0){//遇到偶数就画圆弧,基数则跳过 canvas.drawarc(progresscircle, startangle+eachangle*i/2, eacharcangle, false, progresspaint); } else{ continue; } } } public float getmin() { return min; } public void setmin(float min) { this.min = min; } public float getmax() { return max; } public void setmax(float max) { this.max = max; } public void setvalue(float value) { this.currentpecent = (int) (( 100f * value) / max); } @override public void onsizechanged(int height, int width) { log.e("progresspainterimp","onsizechanged执行"); this.width = width; this.height = height; initinternalcircle(); } public int getcolor() { return color; } public void setcolor(int color) { this.color = color; progresspaint.setcolor(color); } }
可以自定义的属性:
<declare-styleable name="circularloadingview"> <attr name="base_color" format="color" /> <!--内层圆环的颜色--> <attr name="progress_color" format="color" /><!--进度圆环的颜色--> <attr name="max" format="float" /><!--最小值--> <attr name="min" format="float" /><!--最大值--> <attr name="duration" format="integer" /><!--动画时长--> <attr name="progress_stroke_width" format="integer" /><!--圆环宽度--> <!--等分(圆弧加间隔),比如arcquantity=100时,表示将有100个圆弧,和100个空白间隔--> <attr name="argquantity" format="integer" /> <!--每段圆弧与圆弧加间隔之和的比例,ratio=0.5表示每个圆弧与相邻的间隔弧度比是1:1--> <attr name="ratio" format="float" /> </declare-styleable>
调用:
main_activity.xml:
<?xml version="1.0" encoding="utf-8"?> <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 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" xmlns:custom="http://schemas.android.com/apk/res-auto" android:background="#ffffff" > <!--自定义控件,继承relativelayout--> <qdong.com.mylibrary.circularloadingview android:id="@+id/simple" custom:base_color="@color/pager_bg" custom:min="0" custom:max="100" custom:argquantity="100" custom:ratio="0.6" custom:progress_color="@android:color/holo_green_light" custom:progress_icon="@mipmap/ic_launcher" custom:duration="1000" custom:progress_stroke_width="28" android:layout_centerinparent="true" android:layout_width="200dp" android:layout_height="200dp"> <relativelayout android:layout_centerinparent="true" android:layout_width="match_parent" android:layout_height="match_parent"> <textview android:layout_centerinparent="true" android:textsize="20sp" android:layout_centerhorizontal="true" android:id="@+id/number" android:text="0" android:gravity="center" android:textcolor="@color/pager_bg" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </relativelayout> </qdong.com.mylibrary.circularloadingview> <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="set_value" android:id="@+id/button" android:layout_alignparentbottom="true" android:layout_alignparentstart="true"/> <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="animation" android:id="@+id/button3" android:layout_aligntop="@+id/button" android:layout_alignparentend="true"/> </relativelayout>
mainactivity:
findviewbyid(r.id.button).setonclicklistener(new view.onclicklistener() { @override public void onclick(view view) { try { mdashedcircularprogress.setvalue(66);//没有动画的,直接设置 } catch (exception e) { e.printstacktrace(); } } }); findviewbyid(r.id.button3).setonclicklistener(new view.onclicklistener() { @override public void onclick(view view) { try { mdashedcircularprogress.setvalue(0);//无动画,归零 mdashedcircularprogress.setvaluewithanimation(100,2000);//带动画 } catch (exception e) { e.printstacktrace(); } } });
github地址:https://github.com/506954774/androidcircularloadingview
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 三星如何把Gear VR的销量做到百万级
下一篇: 荣耀手表S1怎么开启翻腕切屏?