目录介绍
1.Animation和Animator区别
2.Animation运行原理和源码分析
2.1 基本属性介绍
2.2 如何计算动画数据
2.3 什么是动画更新函数
2.4 动画数据如何存储
2.5 Animation的调用
3.Animator运行原理和源码分析
3.1 属性动画的基本属性
3.2 属性动画新的概念
3.3 PropertyValuesHolder作用
3.4 属性动画start执行流程
3.5 属性动画cancel和end执行流程
3.6 属性动画pase和resume执行流程
3.7 属性动画与View结合
好消息
博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计47篇[近20万字],转载请注明出处,谢谢!
如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!
[01.动画机制总结]()
1.Animation和Animator区别
对于 Animation 动画:
实现机制是,在每次进行绘图的时候,通过对整块画布的矩阵进行变换,从而实现一种视图坐标的移动,但实际上其在 View内部真实的坐标位置及其他相关属性始终恒定.
对于 Animator 动画:
Animator动画的实现机制说起来其实更加简单一点,因为他其实只是计算动画开启之后,结束之前,到某个时间点得时候,某个属性应该有的值,然后通过回调接口去设置具体值,其实 Animator 内部并没有针对某个 view 进行刷新,来实现动画的行为,动画的实现是在设置具体值的时候,方法内部自行调取的类似 invalidate 之类的方法实现的.也就是说,使用 Animator ,内部的属性发生了变化
或者更简单一点说
前者属性动画,改变控件属性,(比如平移以后点击有事件触发)
后者补间动画,只产生动画效果(平移之后点无事件触发,前提是你fillafter=true)
2.Animation运行原理和源码分析
2.1 基本属性介绍
上一篇文章已经对补间动画做了详细的说明,不过这里还是需要重复说一下动画属性的作用
mStartTime:动画实际开始时间
mStartOffset:动画延迟时间
mFillEnabled:mFillBefore及mFillAfter是否使能
mFillBefore:动画结束之后是否需要进行应用动画
mFillAfter:动画开始之前是否需要进行应用动画
mDuration:单次动画运行时长
mRepeatMode:动画重复模式(RESTART、REVERSE)
mRepeatCount:动画重复次数(INFINITE,直接值)
mInterceptor:动画插间器
mBackgroundColor:动画背景颜色
mListener:动画开始、结束、重复回调监听器
2.2 如何计算动画数据
首先进入Animation类,然后找到getTransformation方法,主要是分析这个方法逻辑,如图所示
那么这个方法中做了什么呢?Animation在其getTransformation函数被调用时会计算一帧动画数据,而上面这些属性基本都是在计算动画数据时有相关的作用。
第一步:若startTime为START_ON_FIRST_FRAME(值为-1)时,将startTime设定为curTime
第二步:计算当前动画进度:
normalizedTime = (curTime - (startTime + startOffset))/duration
若mFillEnabled==false:将normalisedTime夹逼至[0.0f, 1.0f]
第三步:判断是否需要计算动画数据:
若normalisedTime在[0.0f, 1.0f],需计算动画数据
若normalisedTime不在[0.0f, 1.0f]:
normalisedTime<0.0f, 仅当mFillBefore==true时才计算动画数据
normalisedTime>1.0f, 仅当mFillAfter==true时才计算动画数据
第四步:若需需要计算动画数据:
若当前为第一帧动画,触发mListener.onAnimationStart
若mFillEnabled==false:将normalisedTime夹逼至[0.0f, 1.0f]
根据插间器mInterpolator调整动画进度:
interpolatedTime = mInterpolator.getInterpolation(normalizedTime)
若动画反转标志位mCycleFlip为true,则
interpolatedTime = 1.0 - normalizedTime
调用动画更新函数applyTransformation(interpolatedTime, transformation)计算出动画数据
第五步:若夹逼之前normalisedTime大于1.0f, 则判断是否需继续执行动画:
已执行次数mRepeatCount等于需执行次数mRepeated
若未触发mListener.onAnimationEnd,则触发之
已执行次数mRepeatCount不等于需执行次数mRepeated
自增mRepeatCount
重置mStartTime为-1
若mRepeatMode为REVERSE,则取反mCycleFlip
触发mListener.onAnimationRepeat
2.3 什么是动画更新函数
下面我们来看一下getTransformation方法中的这一行代码applyTransformation(interpolatedTime, outTransformation),然后进去看看这个方法。如下所示
这个方法的用途是干啥呢?从这个英文解释中可以得知:getTransform的助手。子类应该实现这一点,以应用给定的内插值来应用它们的转换。该方法的实现应该总是替换指定的转换或文档,而不是这样做的。
都知道Animation是个抽象类,接着我们这些逗比程序员可以看看它的某一个子类,比如看看ScaleAnimation中的applyTransformation方法吧。
是否设定缩放中心点:
若mPivotX==0 且 mPivotY==0:transformation.getMatrix().setScale(sx, sy)
否则:transformation.getMatrix().setScale(sx, sy, mPivotX, mPivotY)
介绍到这里还是没有讲明白它的具体作用,它是在什么情况下调用的。不要着急,接下来会慢慢分析的……
2.4 动画数据如何存储
可以看到applyTransformation(float interpolatedTime, Transformation t)这个方法中带有一个Transformation参数,那么这个参数是干