首页 > 系统 > Android > 正文

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

2019-10-21 21:26:03
字体:
来源:转载
供稿:网友

一、效果图

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,欢迎有兴趣的朋友去看看。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表