Android 自定义波浪动画 --"让进度浪起来~"
原文链接:http://www.jianshu.com/p/0e25a10cb9f5
waveview
《Android 自定义波浪动画之"让进度浪起来~"》
转载请注明来自 傻小孩b_移动开发(http://www.jianshu.com/users/d388bcf9c4d3)喜欢的可以关注我,不定期总结文章!您的支持是我的动力哈!
前言
首先贝塞尔曲线原理我在这里就不多说了,今天的重点还是讲下怎么实现波浪进度的实现原理,所以想要了解下贝塞尔曲线的程序yuan,请自己百度或者谷歌下哈,多谢合作~如果开发有什么问题也可以直接加入我的QQ群,详情请看我的个人简介。
演示
waveview.gif
WaveView 实现
(一)如何确定初始化的位置?
首先
在实现一个自定义View的时候,我们先来观察下想要的动画效果分为几个层次,如图所示:
1、向右的贝塞尔曲线,这里用“normal wave”来表示。
作用:一直匀速向左的波浪曲线,作为波浪的前景
2、向右的贝塞尔曲线,这里用“rolling wave”来表示。
作用:为了是波浪效果更佳逼真,所以添加了一个向右匀速的波浪曲线,并且滚动速度是“normal wave”的一半
3、波浪上升高度,这里用“wave height”来表示。
作用:高度代表进度,可以根据设置的当前进度progress与最大进度max动态变化
其次
在这里我们先要来说下贝塞尔曲线应该怎么画。刚开始,有可能有程序yuan想过,画一个无限长(例如 Integer.MAX_VALUE),足够大了、固定周期的赛贝尔曲线,然后开启动画让他固定一个方向移动即可。的确,这种实现方式是可以的,但是感觉资源特别浪费,有可能还会出现内存溢出、响应异常等。所以答案:不建议!
当然,上面那个思路,我是有着手尝试过啦。最后还是择优选择了另一个思路,画出两个周期的贝塞尔曲线,当第一个贝塞尔曲线滑动到最后一个Point、接近第二个贝塞尔曲线的开始Point的时候,直接让他复位,恢复到最初时候的状态,这种绘画效果还是看起来比无限长的贝塞尔曲线效果没区别的。所以,每一次,我们需要计算4n +1个Point点,为什么要4n+1个点?下面图片说明:
Wave_1.png
最后
就是整个闭合区间的填充,如图所示:
wave_2.png
我们看下动画里面,初始化Point的关键代码:
/**
* Initialize the original wave arts collection point , including normal wave ,rolling wave
*/
private void initPoint(){
if (isInitPoint){
isInitPoint = false;
pointList.clear();
shadpointList.clear();
WAVE_WIDTH = (float) (VIEW_WIDTH / 2.5);//这里开发 我直接设置波浪宽度为整个View的四分之一宽度
WAVE_HEIGHT = VIEW_HEIGHT/getWaveHeight();//波浪高度根据速度改变
dy = VIEW_HEIGHT;//Started from the bottom, when the height is rise, dy gradually reduce
//How many points calculated maximum support
int n = Math.round(VIEW_WIDTH / WAVE_WIDTH);
//start point for normal wave
int startX = 0;
Log.i(TAG,"begin point ("+DensityUtil.px2dip(mContext,startX)+" , "+DensityUtil.px2dip(mContext,dy)+")");
for (int i = 0; i < 4*n+1; i++) {
....
pointList.add(point);
}
// start point for rolling wave
startX = (int) VIEW_WIDTH;
for (int i = 0; i < 4*n+1; i++) {
....
shadpointList.add(point);
}
}
}
从上面的代码,我们可以观察到“normal wave”和“rolling wave”初始化Point各自存储在一个list上面,并且先根据波浪的宽度与整个View的宽度,计算出最多支持多少个初始化点(非控制点,一个周期最多三个Point) int n = Math.round(VIEW_WIDTH / WAVE_WIDTH); 因此便能计算出4n+1个point的初始化位置。
(二)如何浪起来?
我们直接定位在移动的动画方法flowingAnimation,根据代码,我们可以了解到使用了属性动画。
private void flowingAnimation(){
ObjectAnimator animator = ObjectAnimator.ofFloat(this,"wave",0,100)
.setDuration(100);
animator.setRepeatCount(INFINITE);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
dx = dx + speed;
shd_dx = shd_dx + speed/2;//Half the speed of the normal waves
....
rerefreshPoints();//更新初始化点
postInvalidate();
}
})
;
animator.start();
}
从代码可以观察到,是属于一个无限循环的动画( animator.setRepeatCount(INFINITE);
),并且动态变化的是dx与shd_dx。因此可以直接观察在绘制onDraw里面,这两个动态变化的变量起了什么作用,以下截取部分onDraw的代码:
for (int i = 0; i < pointList.size(); i++) {
int j = i + 1;
if (pointList.size() > i) {
float start1 = pointList.get(i).x;
wavePath.moveTo(start1, dy);//+dy
if (j % 2 == 0 && j >= 2) {
...
} else {
....
}}
}
....
for (int i = 0; i < shadpointList.size(); i++) {
int j = i + 1;
if (shadpointList.size() > i) {
float start1 = shadpointList.get(i).x + shd_dx;
shadPath.moveTo(start1, dy);//+dy
if (j % 2 == 0 && j >= 2) {
....
} else {
....
}
}
}
应该很明显可以观察到,dx是改变“normal wave”周期的起点,shd_dx是改变“rolling wave”周期起点,因此间接使贝塞尔曲线双向”浪起来“,有了波浪的效果。
(三)如何浮起来?
直接进入动画,观察动态变化的变量
private void riseAnimation(){
....
if (dy > 0) {
...
ValueAnimator animator = ValueAnimator.ofFloat(0, s)
.setDuration(500);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
...
dy = s;
Log.i("yuan", "move m " + m + "dy " + dy);
}
});
animator.start();
beforDy = sum_dy - sum_dy * progressRatio;//save the last time the higher level
}
}
从代码可以观察到,动态变化的是dy,因此波浪浮动的高度由dy所决定,这里难点是这么计算出当我们设置max和progress的时候,动态去变化dy,这里我用一张图来解释下:
(四)回调监听
感觉回调监听感觉没有好说的~
首先WaveView是在onDraw进行回调的,但是这里来有个小问题,如果我们频繁的绘制,不处理的话每一次都会进行回调,这样也会造成不必要的浪费。因此这里,简单记录上次的进度,通过对比,不同才回调。
(五)总结
二十几天没总结,这期间搞了点东西,也经历了一个放松的国庆~当然,同志们也不能将开发落下~最后还是:我们也不能只是搬运代码的“程序猿”,更重要我们是需要写出更高质量的代码,创造的“程序猿”。下面附上源码,如果喜欢的话给个star哈~谢谢:
使用方法,可以直接上github看README
傻小孩b mark共勉,写给在成长路上奋斗的你
喜欢就为我点下喜欢、给我个github的star吧~ 感谢各位读者阅读。
Android 自定义波浪动画 --"让进度浪起来~"的更多相关文章
- Android 自定义帧动画
Android 自定义帧动画 Android L : Android Studio 帧动画 和gif图片类似,顺序播放准本好的图片文件:图片资源在xml文件中配置好 将图片按照预定的顺序一张张切换,即 ...
- Android自定义窗口动画
第一步,设置出现和消失的xml 1.在res/anim下创建enter_anim.xml,设置窗口出现的动画 <?xml version="1.0" encoding=&qu ...
- 实例源码--Android自定义Gallery动画效果
相关文档与源码: 下载源码 技术要点: 1.自定义控件的使用 2.Gallery控件的使用实例 3.详细的源码注释 ...... 详细介绍: 1.自定义控件的使用 本套源码通过自定义控件的方式,继 ...
- Android自定义一款带进度条的精美按键
Android中自定义View并没有什么可怕的,拿到一个需要自定义的View,首先要做的就是把它肢解,然后思考每一步是怎样实现的,按分析的步骤一步一步的编码实现,最后你就会发现达到了你想要的效果.本文 ...
- Android 自定义PopupWindow动画效果
public class RollActivity extends Activity { private View view; private Button btn; private PopupWin ...
- Android 自定义漂亮的圆形进度条
公司有这样一个需求,实现这个圆弧进度条 所以,现在就将它抽取出来分享 如果需要是圆帽的就将,下面这句代码放开即可 mRingPaint.setStrokeCap(Paint.Cap.ROUND);// ...
- Android 自定义View修炼-仿360手机卫士波浪球进度的实现
像360卫士的波浪球进度的效果,一般最常用的方法就是 画线的方式,先绘sin线或贝塞尔曲线,然后从左到右绘制竖线,然后再裁剪圆区域. 今天我这用图片bitmap的方式,大概的方法原理是: (1)首先用 ...
- android采用MVP漫画APP、适配刘海屏、小黄车主界面、录音波浪动画、综合APP等源码
Android精选源码 一款采用MVP架构的仿完整漫画APP源码 Android适配刘海屏幕 基于Xmpp协议的即时通讯社交软件(客户端+服务端) Android小黄车(ofo)app主页菜单效果 一 ...
- Android 自定义 View 圆形进度条总结
Android 自定义圆形进度条总结 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 微信公众号:牙锅子 源码:CircleProgress 文中如有纰漏,欢迎大家留言指出. 最近 ...
随机推荐
- 【axc】简单的线性动画绘制
在一个View上绘制一条直线 然后做出相应的动画效果 可以这样封装三个方法: /** * 划线工具 * * @param lineArray 线段的点数组 NSValue 类型 默认第一 ...
- 解析Json需要设置Mime
IIS6.0 1.打开IIS添加Mime项 关联扩展名:*.json内容类型(MIME):application/x-javascript 2.添加映射: 位置在IIS对应站点右键属性:”主 ...
- docker images之间相互通信 link
同一个host上的两个container 首先启动一个nginx. container起名叫netease_nginx docker run --detach --name netease_nginx ...
- php随机数、时间、字符串函数,正则,数组函数
<?php//1.随机数和时间//echo rand(); //随机数生成器//echo rand(0,10); //生成某个范围内的随机数 //echo time(); //取当前时间戳//e ...
- mysqladmin note
hr,fresh meat!! --------------------------------------------------- 15 Practical Usages of Mysqladmi ...
- Java基础之扩展GUI——使用对话框创建文本元素(Sketcher 4 creating text elements)
控制台程序. 为了与Sketcher中的其他元素类型保持一致,需要为Elements菜单添加Text菜单项和工具栏按钮.还需要定义用来表示文本元素的类Element.Text. 1.修改Sketche ...
- Velocity(5)——#set指令
引用可以让模板设计者生成动态内容,而指令允许设计者真正的负责页面的展现和内容. 指令是以#开头,后面紧跟一个关键字,比如if,else,foreach等.而这个关键字,是可以被放在{}中间的.这是规范 ...
- Java中String类的方法及说明
String : 字符串类型 一. String sc_sub = new String(c,3,2); // String sb_copy = new String(sb) ...
- cookie的三种操作方法
1,jquery.cookie.js 这一篇文章已经写的很详细了: http://www.cnblogs.com/afuge/archive/2013/07/03/3169048.html 2,原生j ...
- struts2实现文件上传、多文件上传和文件下载
总结的两个问题,就是struts2上传下载的时候对属性名配置要求非常严格: 第一:上传的时候 private File file; private String fileContentType; pr ...