Android水波纹载入控件CircleWaterWaveView使用详解

作者:一语成空 时间:2021-10-27 23:06:58 

一、效果图

Android水波纹载入控件CircleWaterWaveView使用详解

本控件已上传Github,欢迎Star和Fork,项目地址:CircleWaterWaveView

二、设计思路

观察效果图,可以看出,该自定义控件由三个部分构成:外圆、内圆、正弦曲线。他们的关系如下图:

Android水波纹载入控件CircleWaterWaveView使用详解

因为控件是动态的,所以我们需要一个线程去不停地绘制,所以我选择了SurfaceView来作为该控件地父类。该控件地核心是如何去绘制波浪,我采用如下的思路来进行内圆下部地绘制。利用内圆与正弦曲线地交集,来绘制。 

Android水波纹载入控件CircleWaterWaveView使用详解

核心代码如下:


/**
* 绘制图像
*
* @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,欢迎有兴趣的朋友去看看。

来源:https://blog.csdn.net/lx578111527/article/details/52797947

标签:Android,水波纹
0
投稿

猜你喜欢

  • Android中 视频屏幕左半部分上下滑动改变亮度右半部分上下滑动改变声音

    2021-08-13 02:57:12
  • Android开发之设置开机自动启动的几种方法

    2021-12-04 20:35:37
  • C#加密解密类实例程序

    2022-01-25 18:17:09
  • C#特性(Attribute)

    2022-08-18 18:34:51
  • 使用Postman传递arraylist数据给springboot方式

    2022-08-27 01:13:01
  • SpringBoot中发送QQ邮件功能的实现代码

    2022-09-25 10:19:59
  • 浅谈SpringBoot中的Bean初始化方法 @PostConstruct

    2022-06-11 07:21:17
  • Java全面细致讲解Cookie与Session及kaptcha验证码的使用

    2021-09-03 23:10:56
  • Android 实现图片生成卷角和圆角缩略图的方法

    2021-08-12 16:14:12
  • java利用Future实现多线程执行与结果聚合实例代码

    2023-09-24 11:07:18
  • 解析C#中@符号的几种使用方法详解

    2022-11-09 03:26:03
  • c#分页读取GB文本文件实例

    2021-09-13 10:18:39
  • 关于synchronized有趣的同步问题

    2021-11-03 05:46:55
  • Spring Boot 配置和使用多线程池的实现

    2022-09-04 19:53:02
  • Android四种常见布局方式示例教程

    2022-05-25 09:35:03
  • Java毕业设计实战项目之在线服装销售商城系统的实现流程

    2023-03-27 00:15:31
  • 基于获取JAVA路径,包括CLASSPATH外的路径的方法详解

    2022-12-20 21:30:03
  • C#利用正则判断输入是否为纯数字、容器类

    2022-10-10 03:00:39
  • Java反射机制详解

    2023-10-01 12:18:04
  • Android 设置应用全屏的两种解决方法

    2023-05-07 01:27:50
  • asp之家 软件编程 m.aspxhome.com