android自定义水波纹,android 自定义view-水波纹进度球
android 进阶之路-自定义view-水波纹进度球
如果你是老司机,一看标题就会就return吧,嘻嘻。
在我们的日常开发中自定义控件还是用的挺多的,设计师或者产品为了更好的漂亮,美观,交互都会做一些牛逼的ui效果图,但是最后实现的还是我们程序员啊。
所以说 自定义view你还是得会的。
要开车了哦,请刷卡...
滴,老司机卡
滴,学生卡
滴,...
刷卡
今天我们要实现的这个view没有太多交互性的view,所以就继承view
自定义view的套路,套路很深
获取我们自定义属性attrs(可省略)
重写onMeasure方法,计算控件的宽和高
重写onDraw方法,绘制我们的控件
这么看来,自定义view的套路很清晰嘛。
我们看下今天的效果图,其中一个是放慢的效果(时间调的长)
效果图1
效果图2
我们按照套路来。
一.自定义属性
看下效果图我们就知道因该需要哪些属性。就不说了。
然后就是获取我们的这些属性,就是用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 thing
bitmapCanvas.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();
android自定义水波纹,android 自定义view-水波纹进度球相关推荐
- android 图片处理过程中添加进度条,『Android自定义View实战』给我一个图标,还你一个水波纹进度球...
前言 我们都知道,平时表现进度的方式有千千万万种(没有UI想不到的,只有你做不到的= =.),其中有一种就是水波纹进度球的形式,网上很多种实现都是直接采用纯色填充的方式,即水波纹都是纯颜色填充,效果看 ...
- android波纹效果弹窗,Android自定义View实现波纹效果
Android自定义View实现波纹效果 时间:2017-05-27 来源:移动互联网学院 1.引言:随着Android智能手机的普及,Android应用得到了大力支持,而Android应用的 ...
- android圆形波纹按钮,android自定义View——圆形波纹扫描效果
蓝牙项目,考虑到后面可能会用到这个扫描的效果,所以参照大神写好的控件,增加了自己需要使用的接口.也顺便巩固一下自定义view中各种零碎的知识点. 需要的效果图 先放一个效果图,点击中心图片开始动画,再 ...
- android覆盖扩散动画,[Android]多层波纹扩散动画——自定义View绘制
之前整理过一些属性动画的基本操作,这一段时间的动画相关需求都安然度过了.直到这次-- 一.另一种动画需求 多数交互中的动画都是让单个页面元素动起来,这种就很适合用属性动画实现.但是对于 多个元素.非页 ...
- android开发控件水波纹,Android实现水波纹控件的方法
有很多app使用过水波纹的这样的效果,看着很酷酷的样子,所以自己就撸码写了一个. 实现思路: 利用贝塞尔曲线绘制圆弧(也就是水波的波纹) 通过动画改变绘制的起始点使水波纹平移 首先,定义我们需要的自定 ...
- Android Material Design 之 Activity 跳转水波纹扩散动画
博主声明: 转载请在开头附加本文链接及作者信息,并标记为转载.本文由博主 威威喵 原创,请多支持与指教. 本文首发于此 博主:威威喵 | 博客主页:https://blog.csdn.net/ ...
- android 自定义progressbar demo,Android自定义View――动态ProgressBar之模仿360加速球
在之前一篇文章中我们讲解了三种ProgressBar的做法,详见-><Android 自定义View--自定义ProgressBar >.这一节中我们模仿360加速球制作一个动态Pr ...
- android前台渲染图片,自定义View
android前台渲染,主要是重写view的ondraw方法,在canvas里操作 自定义MyView类 package com.ssln;import android.annotation.Supp ...
- 球体动画Android,Android自定义View实现简单炫酷的球体进度球实例代码
前言 最近一直在研究自定义view,正好项目中有一个根据下载进度来实现球体进度的需求,所以自己写了个进度球,代码非常简单.先看下效果: 效果还是非常不错的. 准备知识 要实现上面的效果我们只要掌握两个 ...
最新文章
- Java并发编程(十一)——原子操作CAS
- 数字原生,创新生长|企业如何打造数字创新的“飞天梦”?
- 【AI不惑境】模型压缩中知识蒸馏技术原理及其发展现状和展望
- WCF系列学习笔记4之绑定详解
- Android全工程编译不过问题汇总
- python代码格式
- Predicate函数式接口
- 做arma模型步骤_互助问答第349期:关于ARMA预测模型的问题
- c语言中栈的作用,栈(Stack)的概念和应用及C语言实现
- Linux 命令(85)—— md5sum 命令
- 关于scala中lazy val的几个注意事项
- python文件下载学习
- “rt.jar is not on its project's build path”
- Cesium 之实现房屋模型拆解
- 解决谷歌自带翻译不出现问题
- Vs code PIO一直loading
- 《Excel高手捷径:一招鲜,吃遍天》一第29招 Excel 文件“减肥瘦身”秘诀
- windows虚拟摄像头开发
- Javascript中的作用域,作用域链
- 萤石视频监控模式的参数decoderPath配置问题
热门文章
- SAP UI5 workthrough 12 sap.m.shell
- how is SAP UI5 Model.setProperty implemented
- Marketing Cloud的notification的OData实现
- 一种简单的不需要查询UI5文档就能获得所有API的小技巧
- SAP Leonardo 机器学习插件的安装
- deactivate Data synchronization
- 如何控制product search attribute支持的操作类型
- how is sap-ui-core.js initialize the reqeust of sap-ui-core-dbg.js
- get metadata in QHD - still has cache logic
- SAP CRM产品主数据的附件信息在搜索时就已经从后台被读取了