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

所属分类: 软件编程 / Android 阅读数: 91
收藏 0 赞 0 分享

一、效果图

本控件已上传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,欢迎有兴趣的朋友去看看。

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

更多精彩内容其他人还在看

Android网络编程之获取网络上的Json数据实例

这篇文章主要介绍了Android网络编程之获取网络上的Json数据实例,本文用完整的代码实例讲解了在Android中读取网络中Json数据的方法,需要的朋友可以参考下
收藏 0 赞 0 分享

Android中的windowSoftInputMode属性详解

这篇文章主要介绍了Android中的windowSoftInputMode属性详解,本文对windowSoftInputMode的9个属性做了详细总结,需要的朋友可以参考下
收藏 0 赞 0 分享

Android网络编程之UDP通信模型实例

这篇文章主要介绍了Android网络编程之UDP通信模型实例,本文给出了服务端代码和客户端代码,需要的朋友可以参考下
收藏 0 赞 0 分享

Android中使用ListView实现漂亮的表格效果

这篇文章主要介绍了Android中使用ListView实现漂亮的表格效果,本文用详细的代码实例创建了一个股票行情表格,需要的朋友可以参考下
收藏 0 赞 0 分享

Android中刷新界面的二种方法

这篇文章主要介绍了Android中刷新界面的二种方法,本文使用Handler、postInvalidate两种方法实现界面刷新,需要的朋友可以参考下
收藏 0 赞 0 分享

Android SDK三种更新失败及其解决方法

这篇文章主要介绍了Android SDK三种更新失败及其解决方法,需要的朋友可以参考下
收藏 0 赞 0 分享

Android学习笔记——Menu介绍(一)

Android3.0(API level 11)开始,Android设备不再需要专门的菜单键。随着这种变化,Android app应该取消对传统6项菜单的依赖。取而代之的是提供anction bar来提供基本的用户功能
收藏 0 赞 0 分享

Android学习笔记——Menu介绍(二)

这次将继续上一篇文章没有讲完的Menu的学习,上下文菜单(Context menu)和弹出菜单(Popup menu)
收藏 0 赞 0 分享

Android学习笔记——Menu介绍(三)

今天继续昨天没有讲完的Menu的学习,主要是Popup Menu的学习,需要的朋友可以参考下
收藏 0 赞 0 分享

Android显示网络图片实例

这篇文章主要介绍了Android显示网络图片的方法,以实例形式展示了Android程序显示网络图片的方法,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多