一、简介
如上图所示:android动画分类大致有两种一种是
View动画
一种是转场动画
。帧动画:将图片一张一张按顺序播放,展现出动画效果。
补间动画:实现动画alpha(淡入淡出),translate(位移),scale(缩放大小),rotate(旋转)等效果,一般采用xml文件形式。
属性动画:(重点)它是对于对象属性的动画。补间动画的内容,都可以通过属性动画实现。
这里我们就不讲帧动画
跟补间动画
,这两个大家可以自己百度一下用法。(另外这篇文章中的动画都是在代码中实现的,如果要看xml的使用方法,可以看看Android 动画使用 scale、alpha、translate、rotate、set 这篇其他人写的这篇文章。
二、属性动画
基本使用 (ViewPropertyAnimator)
上面是最基本的使用,api提供的有移动
、旋转
、缩放
、透明
,看下面的api:
上面的api中可以看到 都存在
绝对
跟相对
(方法后面-by
)的方法,其中绝对的方法以上面的代码为例子,区别是:translationX(400f)
代表将translationX
变成400translationXBy(400f)
代表将translationX
增加400
这么多api就不做逐一展示了。
ObjectAnimator
1. 基本的使用方式:
- 用 ObjectAnimator.ofXXX() 创建 ObjectAnimator 对象;
- 添加时长、差值器等各种参数
- 用 start() 方法执行动画。
上面是对一个系统提供的View
进行动画展示,主要方法是ObjectAnimator.ofFloat(imag_view,View.ROTATION,0f,180f)
第一个参数:传入要进行属性动画的view
第二个参数:要变化的属性值,这里是传入View.ROTATION
,也就是"rotation"
第三个参数:属性起始值 第四个参数:属性结束值
后面还可以加入多个参数值,从第三个参数开始到最后第n个参数,表示属性开始 ->中间值->中间值.... ->结束值注意一点:并非所有的属性都是可以有set
get
方法,可以进行属性动画。
2. 自定义View动画
自定义View属性动画以及使用的步骤:
- 为要改变的属性添加setter/getter方法
- setter方法中调用
invalidate()
使其重新绘画- 在onDraw()中根据改变的属性绘画出你要的效果
- 使用的时候跟ObjectAnimator基本使用方式一致
大致的模板代码
真正的实现与调用
这里设置了
OvershootInterpolator
插值器,使得它可以超过后回弹回来。这里可以使用PropertyValuesHolders.ofKeyframe()
做到类似效果,可以翻到下面对应内容看一下 #####ValueAnimator 这个是ObjectAnimator
的父类,这个我并没怎么接触,后期再补充吧
2. 设置监听器
设置ObjectAnimator
的监听器
设置点击事件监听
点击顺序 (这里点击开始按钮是重新初始化动画,请大家不要误解) 开始start -> 暂停pause ->继续执行resume->结束end 开始start->取消cancel 开始start->结束end
上面是点击产生的log
日志,其中有个addUpdateListener
监听我没有打印信息,因为动画运行中就会不停打印出来,所以就没有打印出来了。 可以看到所有的状态都是可以有回调方法监听的。
这里有个方法要注意一下 cancel()
跟end(
)这个两个方法。
如果动画是已经结束了
end()
的时候,就不会有回调onAnimationCancel
跟onAnimationEnd
两个监听方法了,看一下ValueAnimator
源码中有体现了
关键代码1:mAnimationEndRequested == true
则不走下面的逻辑,设置true
是在关键代码4
中设置的,也就是说当动画结束调用了endAnimation()
就不会调用到两个回调onAnimationCancel
跟onAnimationEnd
。 关键代码2跟3跟5:就是动画未结束,所以调用了回调onAnimationCancel()
再调用回调onAnimationEnd()
小结:当调用cancel()的时候,动画未结束时则回调
onAnimationCancel()
跟onAnimationEnd()
,当动画结束时,则不会调用任何监听回调方法
end
方法有时候会回调两个回调 分别是onAnimationStart
跟onAnimationEnd
,看一下ValueAnimator
源码中的逻辑
从上面的逻辑可以看到,当调用到!mRunning == true
的时候,会调用startAnimation()
导致回调多一个onAnimationStart
方法。
小结: 当调用
end()
的时候,如果动画处于运行中,则回调onAnimationEnd
,如果不处于运行中,则回调onAnimationStart
跟onAnimationEnd
。
设置ViewPropertyAnimator
的监听器
相比ObjectAnimator
的监听器,这里的ViewPropertyAnimator
多了两个回调方法
withStartAction
跟withEndAction
分别在开始跟结束调用,但是只会被调用一次。setListener
中的onAnimationRepeat
回调不会被调用,因为ViewPropertyAnimator
不支持重复 其它的回调跟ObjectAnimator
一致
三. 属性动画组合
ViewPropertyAnimator
改变尺寸同时改变透明度,下面这种写法是几种动画一块运行的
PropertyValuesHolder
ObjectAnimator
使用时则是要通过PropertyValuesHolder
来实现 上面的代码可以用
PropertyValuesHolders.ofKeyframe()同一个属性拆分
ofKeyframe
(关键帧),可以把同一个动画属性拆分成多个阶段
实现类似interpolator = OvershootInterpolator()
插值器超过结束值后再回弹的效果
AnimatorSet
也是组合动画的,可以让多个动画配合执行,不过它可以让动画先后有序执行~~ playTogether
(同时执行)、playSequentially
(顺序执行) 精确配置顺序with()
,before()
,after()
解释一下上面的代码 上面使用 AnimatorSet
将多个ObjectAnimator
放在一块运行,并且playTogether(animator2,animator3)
代表一起运行
playSequentially(animator1,animator4)
代表先后顺序运行
所以就有了下面的效果图 (x轴、y轴方向放大跟透明度由0-1)是一起的,然后在x轴方向移动。
上面的播放逻辑也可以使用精确配置顺序with(),before(),after()来实现
注意:每个传入给
AnimatorSet
的animator
可以自己定义自己的动画运行时间、差值器等,但是如果在AnimatorSet
设置了运行时间的话则以在AnimatorSet
设置的为准。