Android水波纹载入控件CircleWaterWaveView使用详解
程序员文章站
2022-06-23 14:57:56
一、效果图
本控件已上传github,欢迎star和fork,项目地址:circlewaterwaveview
二、设计思路
观察效果图,可以看出,该自定义控件由...
一、效果图
本控件已上传github,欢迎star和fork,项目地址:circlewaterwaveview
二、设计思路
观察效果图,可以看出,该自定义控件由三个部分构成:外圆、内圆、正弦曲线。他们的关系如下图:
因为控件是动态的,所以我们需要一个线程去不停地绘制,所以我选择了surfaceview来作为该控件地父类。该控件地核心是如何去绘制波浪,我采用如下的思路来进行内圆下部地绘制。利用内圆与正弦曲线地交集,来绘制。
核心代码如下:
/** * 绘制图像 * * @author luxun */ private void drawcanvas(canvas canvas) { if (canvas == null) return; //画背景圆圈 canvas.setdrawfilter(new paintflagsdrawfilter(0, paint.anti_alias_flag | paint.filter_bitmap_flag)); canvas.drawcircle(mcenterpoint.x, mcenterpoint.y, moutradius, moutcirclepaint); canvas.drawcircle(mcenterpoint.x, mcenterpoint.y, mradius, mcirclepaint); if (mstart) { //计算正弦曲线的路径 int mh = mcenterpoint.y + mradius - mcurrenthight; int length = 2 * moutradius; path path = new path(); path.moveto(0, mh); for (int i = 0; i < length; i++) { int x = i; int y = (int) (math.sin(math.toradians(x + mtranx) / amplitude) * mradius / increase); path.lineto(x, mh + y); } path.lineto(length, mh); path.lineto(length, mcenterpoint.y + mradius); path.lineto(0, mcenterpoint.y + mradius); path.lineto(0, mh); canvas.save();//保存画布状态 //这里与圆形取交集,除去正弦曲线多画的部分 path pc = new path(); pc.addcircle(mcenterpoint.x, mcenterpoint.y, mradius, path.direction.ccw); canvas.clippath(pc, region.op.intersect);//切割画布 canvas.drawpath(path, mwaterpaint); //绘制文字 canvas.drawtext(flownum + "%", mcenterpoint.x, mcenterpoint.y + mtextsise / 2, mtextpaint); canvas.restore();//恢复画布状态 } }
三、性能优化
绘制线程如下:
/** * 绘制界面的线程 * * @author luxun */ private class renderthread implements runnable { @override public void run() { // 不停绘制界面,这里是异步绘制,不采用外部通知开启绘制的方式,水波根据数据更新才会开始增长 while (isdrawing) { if (mwatertaget > mcurrenthight) { mcurrenthight = mcurrenthight + mupspeed; if (mwatertaget <= mcurrenthight) { mcurrenthight = mwatertaget; } } if (mstart) { if (mtranx > mradius) { mtranx = 0; } mtranx -= mwaterspeed; } drawui(); systemclock.sleep(25);//控制刷新速率,减少cpu占用 } } }
通过为surfaceholder添加监听,来控制绘制线程。当控件被隐藏不在前台显示时,自动结束绘制线程,当控件显示在前台时,再次开启绘制。
@override public void surfacecreated(surfaceholder surfaceholder) { isdrawing = true; new thread(renderthread).start(); } @override public void surfacechanged(surfaceholder surfaceholder, int format, int width, int height) { int minlength = math.min(width, height); moutradius = minlength / 2; mradius = (int) (0.5 * (minlength - moutstrokewidth)); mcenterpoint = new point(minlength / 2, minlength / 2); if (progress != 0) { setprogress(progress); } } @override public void surfacedestroyed(surfaceholder surfaceholder) { isdrawing = false; }
四、属性化
部分设置属性,除了通过代码设置外,同时也加入了在xml文件中,直接以属性赋值的操作。
app:textcolor="#00ff00" app:watercolor="#00ff00" app:strokecolor="#00ff00" app:backgroudcolor="#00ff00" app:amplitude="1.0"[水波振幅] app:max="1000" app:progress="500" app:increase="6.0"[水波涨幅] app:upspeed="3"[上涨速度] app:waterspeed="8"[移动速度] app:strokesize="4dp" app:textsize="20dp"
五、后记
代码已经上传github,欢迎有兴趣的朋友去看看。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。