Android UI系列之Path也能做酷炫动画
来源:互联网 发布:sql server2000客户端 编辑:程序博客网 时间:2024/05/17 08:18
转载自:http://blog.csdn.net/zxt0601/article/details/53040506
一 概述
原本只是想模仿一下我魂牵梦萦的StoreHouse效果,没想到意外撸出来一个工具库。
最简单用法,给我一个path(可以有多段),我还你一个动画。
I have a path.I have a view. (Oh~),Path(Anim)View.
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
先看效果图:(真机效果更棒哦,我自己的手机是去年某款599的手机,算是低端的了,6个View一起动画,不会卡,查看GPU呈现模式,95%时间都处于16ms线以下。性能还可以的)
其中
图1 是普通逐渐填充的效果,无限循环。
图2 是仿StoreHouse 残影流动效果。(但与原版并不是完全一模一样,估计原版不是用Path做的)
图3 是逐渐填充的效果,设置了只执行一次。
图4 是仿StoreHouse效果。数据源来自R.array.xxxx
图5 是另一种自定义PathAnimHelper实现的自定义动画效果。类似Android L+ 系统进度条效果。
图6 是仿StoreHouse效果,但是将动画时长设置的很大,所以能看到它逐渐的过程。
参数
目前可配参数:
1 绘制方面,支持绘制Path的前景 背景色。
- 1
- 2
- 1
- 2
2 动画方面,目前支持设置动画的时长,是否无限循环等。
- 1
- 2
- 1
- 2
3 仿StoreHouse风格的View,还支持设置残影的长度。
- 1
- 2
- 1
- 2
4 当然你可以拿到Paint自己搞事情:
- 1
- 2
- 1
- 2
数据源:
PathAnimView的数据源是Path。(给我一个Path,还你一个动画View)
所以内置了几种将别的资源->Path的方法。
1 直接传string。 StoreHouse风格支持的A-Z,0-9 “.” “- ” ” “(源自百万大神的库文末也有鸣谢,)
- 1
- 2
- 1
- 2
2 定义在R.array.xxx里
- 1
- 2
- 1
- 2
3 简单的SVG(半成品)
以前从gayHub上找了一个SVG-PATH的转换类:SvgPathParser,现在派上了用场,简单的SVG-PATH,可以,复杂的还有问题,还需要继续寻找更加方案。
20170104更新:
完善的方案已经找到,博文:http://blog.csdn.net/zxt0601/article/details/54018970
轻松实现图片->SVG->PATH.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
简单用法API
1 xml定义
普通PathAnimView
效果如图1 3。动画是 进度填充直到满的效果。
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
高仿StoreHouse风格AnimView:
这种View显示出来的效果如图2 4 6 。动画是 残影流动的效果。
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
2 开始动画
- 1
- 1
3 停止动画
- 1
- 1
4 清除并停止动画
- 1
- 1
稍微 搞基 高级点的用法预览
看到这里细心的朋友可能会发现,上一节,我没有提第5个图View是怎么定义的, 而且第五个View的效果,貌似和其他的不一样,仔细看动画是不是像android L+的系统自带进度条ProgressBar的效果?
那说明它的动画效果和我先前提到的两种不一样,是的,一开始我撸是照着StoreHouse那种效果撸的,这是我第二天才扩展的。
高级的用法,就是本控件动画的扩展性。
你完全可以通过继承PathAnimHelper类
,重写onPathAnimCallback()
方法,扩展动画,图5就是这么来的。
先讲用法预览,稍后章节会详解。
用法:
对任意一个普通的PathAnimView,设置一个自定义的PathAnimHelper类即可:
- 1
- 2
- 1
- 2
自定义的PathAnimHelper类:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
伸手党看到这里如果感兴趣,就可以直接一步gayhub了
(https://github.com/mcxtzhang/PathAnimView)
后文比较长,需要自带耐心观看。
二 架构预览
这里我简单画了一下本文介绍的几个类的类图:
对于重要方法和属性标注了一下。
我们的主角PathAnimView
继承自View,是一个自定义View。
它内部持有一个PathAnimHelper
,专注做Path动画。它默认的实现是 逐渐填充 的动画效果。
一般情况下只需要更换PathAnimHelper
,PathAnimView
即可做出不同的动画。(图1第5个View)
但是如果需要扩充一些动画属性供用户设置,例如仿StoreHouse风格的动画View,想暴露 残影长度 属性供设置。
我这里采用的是:继承自PathAnimView
,并增加属性get、set 方法,并重写getInitAnimHeper()
方法,返回自定义的PathAnimHelper
。
如StoreHouseAnimView
继承自PathAnimView
,增加了残影长度的get、set方法。并重写getInitAnimHeper()
方法,返回StoreHouseAnimHelper
对象。 StoreHouseAnimHelper
类继承的是PathAnimHelper
。
三 基础类的实现:
基础类是PathAnimView
和PathAnimHelper
。
1 PathAnimView
先看PathAnimView
:
这里我将一些不重要的get、set方法和构造方法剔除,留下比较重要的方法。
一个做路径动画的View
* 利用源Path绘制“底”
* 利用动画Path 绘制 填充动画
* 通过mPathAnimHelper 对SourcePath做动画:
* 一个SourcePath 内含多段Path,循环取出每段Path,并做一个动画
代码本身不难,注释也比较详细,核心的话,就是onDraw()
方法咯:
我这里用平移做的paddingLeft、paddingTop。
先利用源Path(mSourcePath)绘制底边的样子。
再利用变化的animPath(mAnimPath)绘制前景,这样animPath不断变化,并且重绘View->onDraw(),前景就会不断变化,形成动画效果。
那么核心就是animPath的的变化了,animPath的变化交由 mPathAnimHelper去做。
核心源码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
2 PathAnimHelper
看看最基础的PathAnimHelper
类是怎么做的,一样省略一些代码:
它是一个PathAnimView的Path动画的工具类
* 一个SourcePath 内含多段(一段)Path,循环取出每段Path,并做一个动画,
* 默认动画时间1500ms,无限循环
* 可以通过构造函数修改这两个参数
* 对外暴露 startAnim() 和 stopAnim()两个方法
* 子类可通过重写onPathAnimCallback()方法,对animPath进行再次操作,从而定义不同的动画效果
值得一提的是,这里的动画时间,是指循环取出SourcePath里的N段Path的总时间。
startAnim()
方法是入口,这个方法会在PathAnimView里被调用。
在startAnim()
方法里,先初始化一个PathMeasure
,以及重置animPath
。
然后利用PathMeasure.nextContour()
方法,循环一遍SourcePath的Path段数count,
利用这个count求出每段小Path应该执行的动画时间:totalDuaration / count
。
然后便调用loopAnim()
方法,循环取出每一段path ,并执行动画。
loopAnim()
方法里,定义一个无限循环的属性动画mAnimator
,
为其设置AnimatorUpdateListener
和onAnimationRepeat
,监听动画的更新和重复。
重点就在这两个监听器里:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
动画每次Update的时候,回调onPathAnimCallback()
方法,在里面对animPath做处理。
对AnimPath处理以后,就可以让View绘制新animPath形成动画了:
然后就是让View重绘,这样就会重走onDraw()方法,就是上一节提到的内容。
onPathAnimCallback()
方法也很简单,按动画进度值,取出当前这一小段的path的部分路径,赋值给animPath。
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
在Repeat监听器里:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
因为SourcePath里是可能含有1+段Path的,这里是合适的时机,利用pathMeasure.nextContour();
循环取出下一段Path, 判断一下新Path的长度,如果为0,说明这一次大循环结束,即用户视觉上的一次动画进度100%了。
这里判断我们设置的isInfinite
属性,
如果是true,说明是循环动画,那么做初始化工作:
清空我们的animPath,初始化pathMeasure。(和startAnim()
方法里的初始化工作一致)。
如果是false,说明动画需要停止,那么手动调用animation.end()
停止动画。(图1,第三个动画)
核心源码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
至此两个最基础的类就讲完了,如此简单就可实现图1第1、3个动画效果。
四 实现StoreHouse风格
我们前面提过,扩展动画,核心是继承PathAnimHelper 重写onPathAnimCallback()
方法即可,所以实现StoreHouse风格,核心类就是StoreHouseAnimHelper
。
1 StoreHouseAnimHelper
- 介绍:仿StoreHouse风格的PathAnimHepler
- 增加了一个动画残影长度的属性:mPathMaxLength,默认值是400
- 因没有找到有用的API,这里实现StoreHouse的方法,是手工计算的,不是很爽。
- 思路是是循环一遍AnimPath,记录里面每一段小Path的length。
- 然后再逆序遍历AnimPath,从后面截取 残影长度 的Path,
- 再复制给AnimPath。
核心代码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
2 StoreHouseAnimView
直接上码了,得益于我们的设计,很简单:
重写getInitAnimHeper()
返回我们的StoreHouseAnimHelper
,并增加残影长度的get、set方法。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
五 动态扩展动画效果
前面提过,如图1第五个动画的效果,就是后期我加入扩展的,分析一下这种效果,它和普通的PathAnimView
的效果只有动画不同,也不需要额外引入属性暴露出去供设置,所以这种场景,我们只需要重写一个PathAnimHelper
类,set给PathAnimView
即可。
代码第一章节也提过,
一点注意的地方就是,这里没有同第四章节那样调用super.onPathAnimCallback(view, sourcePath, animPath, pathMeasure, animation);
。
因为第四章仿StoreHouse的效果,是在第三章的效果基础之上加工而成的。所以需要PathAnimHeper
先处理一下。
而我们这里实现的仿系统ProgressBar的效果,则是完全重写的。
核心方法如下重写,很简单,不再赘述:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
六 总结&待完善:
总结起来就是 I have a path.I have a view. (Oh~),Path(Anim)View.
利用这条裤子,只要传一个Path进去,就可以实现多姿多彩的酷炫Path动画,如果对动画不满意,还可以自己动态扩展。
目前最急需完善的:
SVG->Android PATH的转换,
希望有知道的兄弟可以告知一下,多谢。
20170104更新:
完善的方案已经找到,博文:http://blog.csdn.net/zxt0601/article/details/54018970
轻松实现图片->SVG->PATH.
代码传送门:喜欢的话,随手点个star。多谢
https://github.com/mcxtzhang/PathAnimView
七 引用致谢
StoreHouse风格点阵资源引用处,也是我第一次看见StoreHouse动画:百万大神的库: https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh
一开始我看到这种动画,我还是个小菜鸡,也不知道怎么实现的,但是一直在我脑海里挥之不去。
后来突然有一天想到可以用Path、PathMeasure做自定义View动画来实现,就开始动笔写了起来。
发现Path的路径不太好获取,于是翻看百万大神的库,发现他并不是使用的Path动画,但是的的确确是利用点阵设置数据源的,于是我就借助了这些最原始的点阵资源,撸出了这么一个Path动画。
最初只是想实现这么一个效果,了却我的心愿,没想到还有意外收获。有了这个Path动画工具类库。
说实话写这么一个东西,我不知不觉也提升了,以前可能不太会把层级分的这么开,利用继承组合的方式去扩展功能。
以前大多还是C V 一份代码改一改,像图上的效果,我可能会分开自定义三个View去做,复制一些重复代码也不在乎,看来坚持会有收获。
希望我们都一起进步。
- Android UI系列之Path也能做酷炫动画
- Android UI 之 TextView系列
- Android UI系列之倒计时
- Android动画系列之补间动画
- Android动画系列之属性动画
- android开发系列之动画
- Android动画系列之概述
- Android动画系列之Bitmap
- Android自定义控件之扫描动画UI
- Android系列之UI组件----Menu菜单
- Android系列之UI组件----Menu菜单
- Android系列之UI组件----Menu菜单
- Android系列之UI组件----Menu菜单
- UI系列_roration旋转动画
- UI动画之画布
- Android UI--动画 Animation
- Android-UI-动画
- Android 动画系列之逐帧(Frame)动画详解
- lintcode--二叉树的中序遍历
- 测试Hadoop程序
- bb史上最浅显易懂的Git教程3 分支管理
- 排序和查找
- 欢迎使用CSDN-markdown编辑器
- Android UI系列之Path也能做酷炫动画
- 【代码笔记】iOS-手机系统版本
- RequestContextListener作用
- SPOJ QTree7 [SET][树链剖分]
- 启动 Eclipse 弹出 "Failed to load the JNI shared library jvm.dll "错误的解决方法
- Spring-Mybatis 搭建经历
- 在Android上玩google-breakpad(崩溃日志收集)
- Tocmcat循环报错java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
- 笔记:nios2中如何结合firmware和software?