如果你是老司机,一看标题就会就return吧,嘻嘻。

在我们的日常开发中自定义控件还是用的挺多的,设计师或者产品为了更好的漂亮,美观,交互都会做一些牛逼的ui效果图,但是最后实现的还是我们程序员啊。
所以说 自定义view你还是得会的。

要开车了哦,请刷卡…

滴,老司机卡

滴,学生卡

滴,…

今天我们要实现的没有太多交互性的view,所以就继承view。

自定义view的套路,套路很深

  • 获取我们自定义属性attrs(可省略)
  • 重写onMeasure方法,计算控件的宽和高
  • 重写onDraw方法,绘制我们的控件

这么看来,自定义view的套路很清晰嘛。

我们看下今天的效果图,其中一个是放慢的效果(时间调的长)


我们按照套路来。

一.自定义属性

<declare-styleable name="WaveProgressView"><attr name="radius" format="dimension|reference" /><attr name="radius_color" format="color|reference" /><attr name="progress_text_color" format="color|reference" /><attr name="progress_text_size" format="dimension|reference" /><attr name="progress_color" format="color|reference" /><attr name="progress" format="float" /><attr name="maxProgress" format="float" /></declare-styleable>

看下效果图我们就知道因该需要哪些属性。就不说了。
然后就是获取我们的这些属性,就是用TypedArray来获取。当然是在构造中获取,一般我们会复写构造方法,少参数调用参数多的,然后走到参数最多的那个。
下面的是获取自定义属性:

TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.WaveProgressView, defStyleAttr, R.style.WaveProgressViewDefault);radius = (int) a.getDimension(R.styleable.WaveProgressView_radius, radius);textColor = a.getColor(R.styleable.WaveProgressView_progress_text_color, 0);textSize = a.getDimensionPixelSize(R.styleable.WaveProgressView_progress_text_size, 0);progressColor = a.getColor(R.styleable.WaveProgressView_progress_color, 0);radiusColor = a.getColor(R.styleable.WaveProgressView_radius_color, 0);progress = a.getFloat(R.styleable.WaveProgressView_progress, 0);maxProgress = a.getFloat(R.styleable.WaveProgressView_maxProgress, 100);a.recycle();

注: R.style.WaveProgressViewDefault是这个控件的默认样式。

二.onMeasure测量

我们重写这个方法主要是根据父控件的宽和高来设置自己的宽和高。

   @Override   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//计算宽和高int exceptW = getPaddingLeft() + getPaddingRight() + 2 * radius;int exceptH = getPaddingTop() + getPaddingBottom() + 2 * radius;int width = resolveSize(exceptW, widthMeasureSpec);int height = resolveSize(exceptH, heightMeasureSpec);int min = Math.min(width, height);this.width = this.height = min;//计算半径,减去padding的最小值int minLR = Math.min(getPaddingLeft(), getPaddingRight());int minTB = Math.min(getPaddingTop(), getPaddingBottom());minPadding = Math.min(minLR, minTB);radius = (min - minPadding * 2) / 2;setMeasuredDimension(min, min);} 

首先该控件的宽和高肯定是一样的,因为是个圆嘛。其实是宽和高与半径和内边距(padding)有关,这里的内边距,我们取上下左右最小的一个。宽和高也选择取最小的。
注:this.width = this.height = min; 包含左右边距。
resolveSize这个方法很好的为我们实现了我们想要的宽和高我慢看下源码。

  public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {final int specMode = MeasureSpec.getMode(measureSpec);final int specSize = MeasureSpec.getSize(measureSpec);final int result;switch (specMode) {case MeasureSpec.AT_MOST:if (specSize < size) {result = specSize | MEASURED_STATE_TOO_SMALL;} else {result = size;}break;case MeasureSpec.EXACTLY:result = specSize;break;case MeasureSpec.UNSPECIFIED:default:result = size;}return result | (childMeasuredState & MEASURED_STATE_MASK);}

如果我们自己写也是这样写。
最后通过setMeasuredDimension设置宽和高。

三.onDraw绘制

关于绘制有很多android 提供了很多API,这里就不多说了。
绘制首先就是一些画笔的初始化。
需要提一下绘制path路径的画笔设置为PorterDuff.Mode.SRC_IN模式,这个模式只显示重叠的部分。

   pathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);pathPaint.setColor(progressColor);pathPaint.setDither(true);pathPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

我们要将所有的绘制 绘制到一个透明的bitmap上,然后将这个bitmap绘制到canvas上。

if (bitmap == null) {bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888);bitmapCanvas = new Canvas(bitmap);}

为了方便计算和绘制,我将坐标系平移padding的距离

 bitmapCanvas.save();//移动坐标系bitmapCanvas.translate(minPadding, minPadding);// .... some thingbitmapCanvas.restore();

3.1绘制圆

     bitmapCanvas.drawCircle(radius, radius, radius, circlePaint);

3.2绘制PATH 路径.

一是要实现波纹的左右飘,和上下的振幅慢慢的减小
绘制这个之前我们需要知道二阶贝塞尔曲线的大致原理。
简单的说就是知道:P1起始点,P2是终点,P1是控制点.利用塞尔曲线的公式就可以得道沿途的一些点,最后把点连起来就是喽。
下面这个图片来于网络:

在android-sdk里提供了绘制贝塞尔曲线的函数rQuadTo方法

public void rQuadTo(float dx1, float dy1, float dx2, float dy2) 
  • dx1:控制点X坐标,表示相对上一个终点X坐标的位移坐标,可为负值,正值表示相加,负值表示相减;
  • dy1:控制点Y坐标,相对上一个终点Y坐标的位移坐标。同样可为负值,正值表示相加,负值表示相减;
  • dx2:终点X坐标,同样是一个相对坐标,相对上一个终点X坐标的位移值,可为负值,正值表示相加,负值表示相减;
  • dy2:终点Y坐标,同样是一个相对,相对上一个终点Y坐标的位移值。可为负值,正值表示相加,负值表示相减;
    这四个参数都是传递的都是相对值,相对上一个终点的位移值。

要实现振幅慢慢的减小我们可以调节控制点的y坐标即可,即:
float percent=progress * 1.0f / maxProgress;
就可以得到[0,1]的
一个闭区间,[0,1]这货好啊,我喜欢,可以来做很多事情。
这样我们就可以根据percent来调节控制点的y坐标了。

//根据直径计算绘制贝赛尔曲线的次数int count = radius * 4 / 60;//控制-控制点y的坐标float point = (1 - percent) * 15;for (int i = 0; i < count; i++) {path.rQuadTo(15, -point, 30, 0);path.rQuadTo(15, point, 30, 0);}

这里给出一个振幅的原理图:

然后就是根据宽来循环周期就可以了

要实现左右波纹只需要控制闭合路径的左上角的x坐标即可,当然也是根据percent喽。
大家可以结合下面这个图来理解下上面的话。

path绘制的完整代码片段。

  //绘制PATH//重置绘制路线path.reset();float percent=progress * 1.0f / maxProgress;float y = (1 - percent) * radius * 2;//移动到右上边path.moveTo(radius * 2, y);//移动到最右下方path.lineTo(radius * 2, radius * 2);//移动到最左下边path.lineTo(0, radius * 2);//移动到左上边// path.lineTo(0, y);//实现左右波动,根据progress来平移path.lineTo(-(1 -percent) * radius*2, y);if (progress != 0.0f) {//根据直径计算绘制贝赛尔曲线的次数int count = radius * 4 / 60;//控制-控制点y的坐标float point = (1 - percent) * 15;for (int i = 0; i < count; i++) {path.rQuadTo(15, -point, 30, 0);path.rQuadTo(15, point, 30, 0);}}//闭合path.close();bitmapCanvas.drawPath(path, pathPaint);

3.3绘制进度的文字

这个就比较简单了,绘制在控件的中间即可。关于文字的坐标计算还是很好理解的。

  //绘制文字String text = progress + "%";float textW = textPaint.measureText(text);Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();float baseLine = radius - (fontMetrics.ascent + fontMetrics.descent) / 2;bitmapCanvas.drawText(text, radius - textW / 2, baseLine, textPaint);

最后别忘了把我们的bitmap绘制到canvas上。
canvas.drawBitmap(bitmap, 0, 0, null);
哦,最后是实用方法,这里我们不用thread+handler,我们用属性动画。
你懂的!!!,like

   ObjectAnimator objectAnimator0 = ObjectAnimator.ofFloat(waveProgressView_0, "progress", 0f, 100f);objectAnimator0.setDuration(3300);objectAnimator0.setInterpolator(new LinearInterpolator());objectAnimator0.start();

至此,也就实现了我们的效果。
最后给出源码的下载地址:
star了不迷路哦。

https://github.com/ta893115871/WaveProgressView

android 自定义view 水波纹进度球相关推荐

  1. android 图片处理过程中添加进度条,『Android自定义View实战』给我一个图标,还你一个水波纹进度球...

    前言 我们都知道,平时表现进度的方式有千千万万种(没有UI想不到的,只有你做不到的= =.),其中有一种就是水波纹进度球的形式,网上很多种实现都是直接采用纯色填充的方式,即水波纹都是纯颜色填充,效果看 ...

  2. android自定义水波纹,android 自定义view-水波纹进度球

    android 进阶之路-自定义view-水波纹进度球 如果你是老司机,一看标题就会就return吧,嘻嘻. 在我们的日常开发中自定义控件还是用的挺多的,设计师或者产品为了更好的漂亮,美观,交互都会做 ...

  3. android波纹效果弹窗,Android自定义View实现波纹效果

    Android自定义View实现波纹效果 时间:2017-05-27     来源:移动互联网学院 1.引言:随着Android智能手机的普及,Android应用得到了大力支持,而Android应用的 ...

  4. android自定义view 模仿win10进度条

    android自定义view 模仿win10进度条 本文已授权微信公众号:鸿洋(hongyangAndroid)在微信公众号平台原创首发. PS:有朋友反映动画无法播放,那是因为PathMeasure ...

  5. android自定义view圆环,Android自定义View实现圆环进度条

    本文实例为大家分享了android自定义view实现圆环进度条的具体代码,供大家参考,具体内容如下 效果展示 动画效果 view实现 1.底层圆环是灰色背景 2.上层圆环是红色背景 3.使用动画画一条 ...

  6. android圆形波纹按钮,android自定义View——圆形波纹扫描效果

    蓝牙项目,考虑到后面可能会用到这个扫描的效果,所以参照大神写好的控件,增加了自己需要使用的接口.也顺便巩固一下自定义view中各种零碎的知识点. 需要的效果图 先放一个效果图,点击中心图片开始动画,再 ...

  7. android自定义WaveView水波纹控件

    WaveView Github Repository and libaray https://github.com/onlynight/WaveView 首先看下演示demo demo中可以看到不同高 ...

  8. Android自定义view之圆形进度条

    本节介绍自定义view-圆形进度条 思路: 根据前面介绍的自定义view内容可拓展得之: 1:新建类继承自View 2:添加自定义view属性 3:重写onDraw(Canvas canvas) 4: ...

  9. android自定义拱形,Android自定义View实现圆弧进度的效果

    前言 Android开发中,常常自定义View实现自己想要的效果,当然自定义View也是Android开发中比较难的部分,涉及到的知识有Canvas(画布),Paint(画笔)等,自定义控件分为三种: ...

最新文章

  1. 配置 腾讯云 SSL 证书 SSL证书实现https,环境:phpStudy下Apache环境
  2. C++ pair(对组)用法
  3. linux远程hadoop,远程调试Hadoop
  4. Java集合框架:总结
  5. oracle 数据库字段名与实体类字段名称不匹配的处理方法
  6. Find them, Catch them POJ - 1703(种类并查集)
  7. Andoid自动判断输入是电话,网址或者Email的方法----Linkify的应用!
  8. 写代码用什么笔记本_1—2千预算,编程、写代码、办公、PS修图笔记本推荐/选购指南...
  9. [BZOJ 5074]小B的数字
  10. mysql中group_concat函数的使用以及separator的用法
  11. Top Down Operator Precedence - 自顶向下算符优先分析法
  12. 手机如何利用IP地址定位城市
  13. mysql查找数据库文件位置
  14. VScode绘制波形图
  15. 第9天 用css画一个五边形和一个六边形
  16. 给大家分享一款非常漂亮的博客
  17. QML 播放 http 协议开头的视频流的一些问题DirectShowPlayerService::doPlay: Unresolved error code 8007000e
  18. 连线游戏Game of Lines
  19. 阿里笔试测评考什么?
  20. Python readline()和readlines()函数:按行读取文件

热门文章

  1. Linux基础_合并,归档,压缩,dump,编辑器
  2. Redis 更新(set) key值 会重置过期时间问题
  3. 你知道云计算,但是你知道“云工作”吗?
  4. SNMP学习(2)——SNMP实战
  5. 资产信息自动化收集系统 Venux
  6. HDU 1233 - 还是畅通工程
  7. 使用ffmpeg快速生成视频截图
  8. 使用jquery 动态操作添加/删除tr td
  9. 词法分析与语法分析简介
  10. Spring AOP面向切面源码解析