这些读书笔记是根据《Android开发艺术探索》和《Android群英传》这两本书,然后将书上的一些知识点做一下记录。方便学习和理解,如果有存在侵犯版权的地方,还麻烦告知。个人强烈建议购买这两本书。真心不错。
本节是和《Android开发艺术探索》中的第7章 “Android动画深入分析” 有关系,建议先买书查看这一章。
[]
Android动画分为三种:View动画,帧动画,属性动画。
View动画通过对View对象不断做图像变换(平移,缩放,旋转,透明度)从而产生动画效果。
帧动画通过顺序播放一系列图像从而产生动画效果。可以简单理解为图片切换动画。
属性动画通过动态改变对象的属性从而产生动画效果。属性动画为API 11的新特性。在低于API 11无法使用属性动画,但是可以通过NineOldAndroids兼容库来使用。
View动画只对动画的起始值和结束值进行赋值,而动画中间执行过程中的属性值则是系统帮我们计算的。属性动画可以控制动画执行过程中的任意时刻的任意属性值。
[]View动画
View动画的作用对象是View,View动画支持4种动画效果:平移动画,缩放动画,旋转动画,透明度动画。View动画还支持自定义。
View动画既可以通过xml来定义,也可以通过代码来动态创建,但是对于View动画来说,建议采用xml来定义动画,因为xml格式的动画可读性更好。
如果采用xml格式来定义动画,可以将动画xml文件存放到res/anim
{}动画集合(AnimationSet < set >)
动画集合可以包括多个动画。
{}平移动画(TranslateAnimation < translate >)
可以使View在水平和竖直方向完成平移的动画效果。
< translate >标签属性:
{}缩放动画(ScaleAnimation < scale>)
可以使View具有放大或者缩小的动画效果。
< scale>标签属性:
默认情况下轴点是View的左上角,这时在水平方向缩放会导致View向左右两个方向同时进行缩放。如果轴点是View的右边界,那么View就只会向左边进行缩放。
{}旋转动画(RotateAnimation < rotate>)
可以使View具有旋转的动画效果。
< rotate>标签属性:
View是围绕着轴点进行旋转的。默认情况下轴点是View的左上角。
注:坐标的值可以有三种格式:以”%”后缀结束,表示相对于View本身的百分比;如果以”%p”后缀结束,表示相对于父View的百分比;如果没有任何后缀,表示相对于View本身具体值。
{}透明度动画(AlphaAnimation < alpha>)
可以改变View的透明度。
< alpha>标签属性:
透明度中0.0为全透明,1.0为不透明,默认为1.0。
{}加载View动画和View动画监听
//加载View动画
Animation animationText= AnimationUtils.loadAnimation(this,R.anim.anim_text);
mTextView.startAnimation(animationText);
//View动画监听
animationText.setAnimationListener(AnimationListener listener);
AnimationListener 接口有三个方法:
void onAnimationStart(Animation animation); //动画开始
void onAnimationEnd(Animation animation); //动画结束
void onAnimationRepeat(Animation animation); //动画重复播放
{}自定义View动画
继承Animation类,重写initialize()和applyTransformation(),其中在initialize()中对一些变量进行初始化工作, 在applyTransformation()中通过矩阵修改动画数值,从而控制动画的实现过程。很多时候采用Camera来简化矩阵变换,其实自定义View动画主要是矩阵变换的过程。在实际开发过程中很少使用自定义View动画。
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
Matrix matrix = t.getMatrix();
......
super.applyTransformation(interpolatedTime, t);
}
float interpolatedTime参数:表示当前动画进行的时间与动画总时间(一般在 setDuration() 方法中设置)的比值,从0逐渐增大到1
Transformation t参数:传递当前动画对象,一般可以通过代码 Matrix matrix = t.getMatrix() 获得 Matrix 矩阵对象,再设置 Matrix 对象,一般要用到 interpolatedTime 参数,以此达到控制动画实现的结果。
t参数: 传递当前动画对象。
applyTransformation()在动画的执行过程中会不断地调用。通过t.getMatrix() 获得 Matrix(矩阵),一般要用到 interpolatedTime 参数来设置Matrix,以此达到控制动画实现的结果。
[]帧动画(AnimationDrawable < animation-list >)
帧动画xml文件存放到res/drawable,
//定义帧动画xml文件
必须要将帧动画作为View的背景,可以通过代码也可以通过xml设置。
mButton.setBackgroundResource();
<....View
....
android:background="@drawable/...." />
开始帧动画
AnimationDrawable animDrawable=(AnimationDrawable)mButton.getBackground()
animDrawable.start();
[]View动画的特殊使用场景
{}ViewGroup控制子元素的出场效果
LayoutAnimation作用于ViewGroup,这样它的子元素出场就会具有动画效果,这种效果主要用在ListView上,它的每个item都以一定的动画的形式出现。
android:delay属性:表示子元素开始动画的时间延迟。比如子元素的入场动画的时间周期是300ms,那么0.5表示每一个子元素都要延迟150ms才能播放入场动画。
android:animation属性:为子元素指定具体的入场动画。
android:animationOrder属性:表示子元素动画的顺序。有3个值分别是:normal,reverse,random。其中normal表示顺序显示,即排在前面的子元素先开始播放入场动画。reverse表示逆向显示,即排在后面的子元素先开始播放入场动画。random表示随机播放入场动画。
为ViewGroup指定android:layoutAnimation=”@anim/……”,对于ListView来说,这样item就具有出场动画效果。
除了使用xml也还可以通过LayoutAnimationController类实现。
{}Activity之间的切换效果
Activity有默认的切换效果,但是也可以自定义切换效果。
Activity切换效果主要用overridePendingTransition(),这个方法必须定义在startActivity()或者finish()之后调用才能生效。否则动画效果不起作用。
//比如Activity A跳转到Activity B,那么exitAnim效果在Activity A,enterAnim效果在Activity B 。
Activity对象.overridePendingTransition(int enterAnim, int exitAnim)
Fragment也可以添加切换动画,主要用FragmentTransaction对象的setCustomAnimations()来添加切换动画。
Activity之间的切换效果还可以给Activity设置样式(android:theme=”@style/….”)来实现,个人觉得用样式比调用方法更简单。
[]属性动画
属性动画可以对任何对象的属性进行动画而不仅仅是View,甚至还可以没有对象。属性动画的效果:在一个时间间隔内完成对象从一个属性值到另一个属性值的改变。只要对象有这个属性,它就能实现动画效果。属性动画的默认时间间隔是300ms。默认的帧率是10ms/帧。
属性动画是在API 11才出现,可以采用开源动画库NineOldAndroids(http://nineoldandroids.com)来兼容以前的版本。NineOldAndroids在API 11以前的版本底层还是采用View动画来实现。
比较常用的属性动画类:ValueAnimator,ObjectAnimator,AnimatorSet。ObjectAnimator继承ValueAnimator,AnimatorSet是动画集合。
属性动画既可以采用代码来实现,也可以采用xml来实现,xml文件存放到res/animator。建议采用代码来实现。因为代码来实现比较简单。更重要的原因是有时一个属性的起始值是无法提前确定的。
{}ObjectAnimator (< objectAnimator >)
android:repeatCount:动画的重复次数。默认值为0,其中 -1表示无限循环。
android:repeatMode:动画的重复模式。有2个值分别是:restart和reverse。其中restart表示连续重复。reverse表示逆向重复,逆向重复是指第一次顺着播放,第二次倒着播放,第三次顺着播放。
android:valueType:intType表示属性的类型为整型,floatType表示属性的类型为浮点型。如果属性的类型为颜色,可以不需要指定。系统会自动对颜色类型的属性做处理。
{}ValueAnimator (< animator >)
{}AnimatorSet (< set >)
android:ordering:子动画播放的顺序。有2个值分别是:together(默认值),sequentially。其中together表示动画集合中的子动画同时播放。sequentially表示动画集合中的子动画按照前后顺序依次播放。
{}xml格式的属性动画加载
Animator animator= AnimatorInflater.loadAnimator(this,R.animator.animator_text);
animator.setTarget(mButton);
animator.start();
{}属性动画的监听
Animator对象.addListener(AnimatorListener listener)
AnimatorListener 接口有四个方法:
void onAnimationStart(Animator animation); //动画开始
void onAnimationEnd(Animator animation); //动画结束
void onAnimationCancel(Animator animation); //动画取消
void onAnimationRepeat(Animator animation); //动画重复播放
ValueAnimator对象.addUpdateListener(AnimatorUpdateListener listener);
注意:动画被取消,onAnimationEnd()也会被调用。所以动画被取消时,会依次调用onAnimationCancel()–> onAnimationEnd()
AnimatorUpdateListener 接口有一个方法:
void onAnimationUpdate(ValueAnimator animation); 监听整个动画过程,动画是由每一帧组成的,每播放一帧就会被调用一次。
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 获取当前动画的进度值,1~100。为ofInt()中设定的值
int currentValule = (int) animation.getAnimatedValue();
// 获取动画当前时间流逝的百分比,范围在0~1之间
float fraction = animation.getAnimatedFraction();
......
}
});
{}代码实现属性动画
ObjectAnimator animator= ObjectAnimator.ofFloat(Object target, String propertyName, float... values);
ObjectAnimator animator= ObjectAnimator.ofInt(Object target, String propertyName, float... values);
ObjectAnimator animator= ObjectAnimator.ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values);
animator.start();
常用属性对应的字符串(propertyName)有:
1,translationX、translationY:控制view对象相对其左上角坐标在X、Y轴上偏移的距离。
2,rotation、rotationX、rotationY:控制view对象绕支点进行2D和3D旋转
3,scaleX、scaleY:控制view对象绕支点进行2D缩放。
4,pivotX、pivotY:控制view对象的支点位置,这个位置一般就是view对象的中心点。围绕这个支点可以进行旋转和缩放处理。
5,x、y:描述view对象在容器中的最终位置,是最初的左上角坐标和translationX、translationY值的累计和。
6,alpha:表示view对象的透明度。默认值是1(完全透明)、0(不透明)。
values对象有一个或多个属性值;当只指定一个属性值,系统默认此值为结束值;当指定两个属性值,系统默认分别为起始值和结束值;当指定三个或三个以上时,系统默认线性插值。
注:如果对象(target)的属性(propertyName)类型是整型调用ofInt(),如果是浮点型调用ofFloat()。不然可能会无效果。
{}AnimatorSet
AnimatorSet可以让多个动画配合执行,比如:多个动画同时进行,一个动画执行完再执行另一个动画。
AnimatorSet的方法:
playSequentially(Animator… items) //多个动画依次执行
playTogether(Animator… items) //多个动画同时执行
play(Animator anim) //返回AnimatorSet.Builder对象
AnimatorSet.Builder有四个方法:
after(Animator anim) //将现有动画插入到传入的动画之后执行
after(long delay) //将现有动画延迟指定毫秒后执行
before(Animator anim) //将现有动画插入到传入的动画之前执行
with(Animator anim) //将现有动画和传入的动画同时执行
{}PropertyValuesHolder
PropertyValuesHolder可以在同一个动画中改变多个属性,还可以通过设置Keyframe(关键帧),把同一个动画属性拆分成多个阶段。
//比如:改变透明度的同时改变尺寸
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("scaleX", 0, 1);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleY", 0, 1);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("alpha", 0, 1);
ValueAnimator valueAnimator = ObjectAnimator.ofPropertyValuesHolder(view, holder1, holder2, holder3);
valueAnimator.start();
//比如:初始帧progress为0,时间进行到一半progress为100,结束帧progress回落到80
Keyframe keyframe1= Keyframe.ofFloat(0, 0);
Keyframe keyframe2= Keyframe.ofFloat(0.5f, 100);
Keyframe keyframe3= Keyframe.ofFloat(1, 80);
PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofKeyframe("progress", keyframe1, keyframe2, keyframe3);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(view, propertyValuesHolder);
objectAnimator.start();
{}ViewPropertyAnimator
ViewPropertyAnimator是Android 3.1增加的功能,View对象调用animate()返回的就是ViewPropertyAnimator对象。
ViewPropertyAnimator viewPropertyAnimator = View对象.animate();
注意:
()其中带By()后缀的是指改变多少,没有带后缀的是指改变为多少。比如:translationX(100) 表示把View的translationX值渐变为100,而translationXBy(100) 则表示把View的translationX值渐变地增加100。
()ViewPropertyAnimator只能做平移,旋转,缩放,透明度动画。
()ViewPropertyAnimator的使用
View对象.animate().
translationX(float value).
rotation(float value).
scaleX(float value).
alpha(float value).
setDuration(long duration).
setInterpolator(TimeInterpolator interpolator);
注意:
()ViewPropertyAnimator也可以设置时间(setDuration())和插值器(setInterpolator())
()start()可以默认不调用,因为使用隐式启动动画,但是动画不会立刻执行,而是ViewPropertyAnimator设置的方法都执行完毕后,动画才会自动启动。当然,也可以显示调用start()来启动动画
()ViewPropertyAnimator设置监听
//设置监听
ViewPropertyAnimator.setListener(new Animator.AnimatorListener(){
//实现方法
})
ViewPropertyAnimator.setUpdateListener(new AnimatorUpdateListener(){
//实现方法
})
//移除监听
ViewPropertyAnimator.setListener(null)
ViewPropertyAnimator.setUpdateListener(null)
ViewPropertyAnimator.withStartAction(Runnable runnable)
ViewPropertyAnimator.withEndAction(Runnable runnable)
注意:withStartAction() / withEndAction() 是一次性的,在动画执行结束后就自动弃掉了,就算之后再重用ViewPropertyAnimator来做别的动画,用它们设置的回调也不会再被调用。
{}插值器(Interpolator)和估值器(Evaluator)
时间插值器:根据时间流逝的百分比来计算出当前属性值改变的百分比。直接控制动画的变化速率,形象点说就是加速度,可以简单理解为变化的快慢。
常用的插值器LinearInterpolator(线性插值器:匀速动画),AccelerateDecelerateInterpolator(加速减速插值器,默认值),DecelerateInterpolator(减速插值器),AccelerateInterpolator(加速插值器),BounceInterpolator(弹跳值器,可以实现弹跳效果)。具体的插值器可以查看这个网址(http://hencoder.com/ui-1-6)
自定义插值器需要实现 TimeInterpolator 接口或者 Interpolator 接口,Interpolator 继承 TimeInterpolator。需要实现接口的getInterpolation(float input)。
input和fraction的关系:input的值决定了fraction的值。input的值是由系统经过计算后传入到getInterpolation()中的,fraction就是getInterpolation()的返回值。
类型估值器:根据当前属性改变的百分比来计算改变后的属性值。系统定义的有IntEvaluator (针对整型属性),FloatEvaluator(针对浮点型属性),ArgbEvaluator(针对Color属性)。
自定义估值器需要实现TypeEvaluator接口,需要实现接口的evaluate()。如果是对其它类型(非int,Float,Color)做动画,那就必须要自定义类型估值算法。
插值器和估值器是实现非匀速动画的重要手段。
{}属性动画的原理
属性动画要求动画作用的的对象提供该属性的get和set方法,属性动画根据外界传递的该属性的初始值和最终值,以动画的效果多次去调用set方法,每次传递给set方法的值都不一样,随着时间的推移,所传递的值越来越接近最终值。
{}属性动画的条件
1,属性动画作用的对象必须要提供属性的set…(),如果动画的时候没有传递初始值,那么还要提供get…(),因为系统要去获取属性的初始值。如果这个条件不满足,程序直接Crash。
2,属性动画作用的对象的set….()对属性所做的改变必须能够通过某种方法反映出来。比如会带来UI的改变之类。如果这个条件不满足,动画无效果但不会Crash。
{}针对属性动画条件的解决方法
1,给你的对象加上set…()和get…(),如果你有权限的话。
这种方式是最简单的,但是往往是不可行的。
2,用一个类来包装原始对象,间接为其提供set…()和get…()。
这种方式是比较常见的。
3,采用ValueAnimator,监听动画过程(addUpdateListener()),在动画过程中修改对象的属性值。
ValueAnimator本身不作用于任何对象,也就说直接使用它没有任何动画效果。它可以对一个值做动画,然后监听其动画过程,在动画过程中修改对象的属性值。
属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的,ValueAnimator对过渡动画值的计算依靠一个时间因子(fraction),而这个时间因子(fraction)是系统由setDuration()设置的动画执行时间通过计算得来的,所以ValueAnimator还负责管理动画的持续时间、播放次数、播放模式、以及对动画设置监听器等。
{}动画的注意点
1,View动画的问题
View动画是对View的影像做动画,并不是真正的改变View的状态。有时可能会出现动画完成后View无法隐藏的问题,即setVisibility(View.GONE)失效。这时只要View对象调用clearAnimation()清除View动画。
2,动画元素的交互
将View平移后,View动画新位置无法触发点击事件,但是老位置可以触发点击事件。3.0之后的属性动画新位置可以触发点击事件,老位置无法触发点击事件。3.0之前的属性动画新位置无法触发点击事件,但是老位置可以触发点击事件。这是因为3.0之前没有属性动画,所谓的属性动画其实底层是View动画来实现。
浅析Android动画系列的三篇文章:
View动画高级实例探究 (一)
http://www.cnblogs.com/wondertwo/p/5295976.html
属性动画与高级实例探究 (二)
http://www.cnblogs.com/wondertwo/p/5312482.html
自定义Interpolator与TypeEvaluator(三)
http://www.cnblogs.com/wondertwo/p/5327586.html
Android属性动画完全解析(上),初识属性动画的基本用法
http://blog.csdn.net/guolin_blog/article/details/43536355
Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法
http://blog.csdn.net/guolin_blog/article/details/43816093
Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法
http://blog.csdn.net/guolin_blog/article/details/44171115