第七章 Android动画深入分析
Android的动画分为三种:View动画,帧动画,属性动画。帧动画属于View动画。
7.1 View动画
View动画的作用对象是View,共有四种动画效果:平移(Translate),缩放(Scale),旋转(Rotate),透明度(Alpha)。
7.1.1 View动画的种类
View动画的保存路径:res/anim/filename.xml。XML格式语法如下:
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
|
<?xml version= "1.0" encoding= "utf-8" ?>
<set xmlns:android= "http://schemas.android.com/apk/res/android"
android:interpolator= "@anim/interpolator_resource"
android:shareInterpolator= "true|false" >
<alpha
android:fromAlpha= "float" <!-- 透明度起始值-->
android:toAlpha= "float" /><!-- 透明度结束值-->
<scale
android:fromXScale= "float" <!--水平方向缩放起始值 -->
android:toXScale= "float" <!--水平方向缩放结束值 -->
android:fromYScale= "float" <!--垂直方向缩放起始值 -->
android:toYScale= "float" <!--垂直方向缩放结束值 -->
android:pivotX= "float" <!--缩放轴点x坐标 -->
android:pivotY= "float" /><!--缩放轴点y坐标 -->
<translate
android:fromXDelta= "float" <!--x的起始位置-->
android:fromYDelta= "float" <!--y的起始位置-->
android:toXDelta= "float" <!--x的结束位置-->
android:toYDelta= "float" /><!--y的结束位置-->
<rotate
android:fromDegrees= "float" <!--起始角度 -->
android:toDegrees= "float" <!-- 结束角度-->
android:pivotX= "float" <!-- 旋转轴点x坐标 -->
android:pivotY= "float" /><!-- 旋转轴点y坐标-->
<set>
...
</set>
</set>
|
<set>标签表示动画集合,对应AnimationSet类,内部还可以嵌套其他动画集合。
android:interpolator 插值器规定动画已怎样的速度运行,默认为加速减速插值器。
android:shareInterpolator 集合中的动画是否和集合共享同一个插值器。
android:duration 动画持续时间
android:fillAfter 动画结束后View是否停留在结束位置。
<scale>、<rotate>中轴点默认情况下是View的中心点(有待验证貌似是左上角)。
在代码中加载xml中定义的动画:
1
2
|
Animation animation = AnimationUtils.loadAnimation( this , R.anim.view1);
button.startAnimation(animation);
|
使用Animation的setAnimationListener方法可以给View动画添加监听。
7.1.2 自定义View动画
原理:继承Animation这个抽象类,然后重写它的initialize和applyTransformation方法,在initialize中做初始化,在applyTransformation中进行相应的矩阵变换即可。通常采用camera来简化矩阵变换的过程。自定义View动画的过程主要就是矩阵变换的过程。例子可参考APIDEMO中的Rotate3dAnimation效果。
7.1.3 帧动画
帧动画其实就是顺序播放一组预先定义好的图片。通过AnimationDrawable来使用帧动画。XML格式语法如下:
1
2
3
4
5
6
7
|
<?xml version= "1.0" encoding= "utf-8" ?>
<animation-list xmlns:android= "http://schemas.android.com/apk/res/android"
android:oneshot= "true|false" >
<item android:drawable= "@mipmap/ic_launcher" android:duration= "500" />
<item android:drawable= "@mipmap/ic_launcher" android:duration= "500" />
<item android:drawable= "@mipmap/ic_launcher" android:duration= "500" />
</animation-list>
|
使用时直接作为View的背景并通过Drawable来播放即可。
1
2
3
|
button.setBackgroundResource(R.drawable.view2);
AnimationDrawable drawable=(AnimationDrawable)button.getBackground();
drawable.start();
|
7.2 View动画的特殊使用场景
7.2.1 LayoutAnimation
作用于ViewGroup,为ViewGroup指定一个动画,这样当它的子元素出场时都会具有这种动画效果。
步骤:
(1)定义LayoutAnimation
1
2
3
4
5
|
<?xml version= "1.0" encoding= "utf-8" ?>
<layoutAnimation xmlns:android= "http://schemas.android.com/apk/res/android"
android:delay= "0.5"
android:animationOrder= "normal"
android:animation= "@anim/anim_item" />
|
android:delay 子元素开始动画的时间延迟,例如子元素设置duration为200ms,则0.5表示每个子元素都需要延迟100ms开能开始播放动画,即第一个经过100ms开始播放,第二个就得经过200ms开始播放,第三个就得经过300ms开始播放,以此类推。
android:animationOrder 子元素动画顺序,normal(顺序显示),reverse(逆向显示),random(随机)。
(2)为子元素指定动画
1
2
3
4
5
6
7
8
9
10
11
12
|
<?xml version= "1.0" encoding= "utf-8" ?>
<set xmlns:android= "http://schemas.android.com/apk/res/android"
android:duration= "300"
android:interpolator= "@android:anim/accelerate_interpolator"
android:shareInterpolator= "true" >
<alpha
android:fromAlpha= "0.0"
android:toAlpha= "1.0" />
<translate
android:fromXDelta= "500"
android:toYDelta= "0" />
</set>
|
(3)为ViewGroup指定android:layoutAnimation属性
1
|
android:layoutAnimation= "@anim/anim_layout"
|
或者通过LayoutAnimationController来为ViewGroup指定动画。
1
2
3
4
5
6
|
Animation animation = AnimationUtils.loadAnimation( this , R.anim.anim_item);
LayoutAnimationController controller= new LayoutAnimationController(animation);
controller.setDelay( 0 .5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
linearlayout.setLayoutAnimation(controller);
|
7.2.2 Activity的切换效果
使用overridePendingTransition(int enterAnim, int exitAnim)方法,注意这个方法必须在startActivity或者finish之后被调用才能生效。
enterAnim——Activity被打开时的动画
exitAnim——Activity退出时的动画
启动Activity:
1
2
3
|
Intent intent = new Intent( this ,TestActivity. class );
startActivity(intent);
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
|
退出Activity:
1
2
3
4
5
|
@Override
public void finish() {
super .finish();
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
}
|
7.3 属性动画
API等级必须大于等于11,存放路径为res/animator/目录下,属性动画可以对任何对象做动画,常见的有ValueAnimator、ObjectAnimator。
7.3.1 使用属性动画
属性动画默认时间间隔为300ms,默认帧率为10ms/帧,可以达到在一个时间间隔内完成对象从一个属性值到另一个属性值的改变。如果想要属性动画兼容低版本系统,需要使用NineOldAndroids这个开源动画库。
举例说明如何使用属性动画:
(1)改变一个对象的translationY属性,让其沿着Y轴向上平移一段距离:它的高度。
ObjectAnimator.ofFloat(myObject,"translationY",-myObject.getHeight());
(2)改变一个View的背景色,让其背景色在3秒内实现用0xFFFF8080到0xFF8080FF的渐变,动画无限循环并加反转效果。
1
2
3
4
5
6
|
ValueAnimator colorAnim=ObjectAnimator.ofInt( this , "backgroundColor" , 0xFFFF8080 , 0xFF8080FF );
colorAnim.setDuration( 3000 );
colorAnim.setEvaluator( new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();
|
属性动画的XML格式语法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<?xml version= "1.0" encoding= "utf-8" ?>
<set xmlns:android= "http://schemas.android.com/apk/res/android"
android:ordering= "sequentially|together" ><!--together:子动画同时播放。sequentially:自动化按照先后顺序依次播放-->
<objectAnimator
android:duration= "int" <!--动画时长-->
android:propertyName= "string" <!--属性名称-->
android:repeatCount= "int" <!--重复次数-->
android:repeatMode= "restart|reverse" <!--重复模式-->
android:startOffset= "int" <!--延迟时间-->
android:valueFrom= "float|int|color" <!--属性起始值-->
android:valueTo= "float|int|color" <!--属性结束值-->
android:valueType= "colorType|intType|floatType|pathType" /><!--属性类型-->
<animator
android:duration= "int"
android:repeatCount= "int"
android:repeatMode= "restart|reverse"
android:startOffset= "int"
android:valueFrom= "float|int|color"
android:valueTo= "float|int|color"
android:valueType= "colorType|intType|floatType|pathType" />
</set>
|
android:repeatCount 动画的循环次数,默认为0,-1为无限循环;
android:repeatMode repeat:连续重复;reverse:逆向重复(第一次播放完后,第二次倒着播放,第三次在重头开始播如此反复)。
在XML中定义好属性动画后在java代码中就可以使用了
1
2
3
|
AnimatorSet set=(AnimatorSet) AnimatorInflater.loadAnimator(context,R.anim.property_animator);
set.setTarget(button);
set.start();
|
实际开发中建议使用代码来实现属性动画,不要使用xml的方式。
7.3.2 理解插值器和估值器
插值器:根据时间流逝的百分比来计算出当前属性值改变的百分比;
估值器:根据当前属性的百分比来计算改变后的属性值。
7.3.3 属性动画监听器
AnimatorListener监听动画的开始、结束、取消、重复播放;
AnimatorUpdateListener 监听整个动画过程。
7.3.4 对任意属性做动画
对object的属性abc做动画,如果想让动画生效需要满足一下两个条件:
(1)object必须要提供setAbc方法,如果动画的时候没有传递初始值,那么还得提供getAbc方法,否则程序直接crash;
(2)object的setAbc对属性abc所做的改变必须能够通过某种方法反映出来,比如带来UI的改变。
如何给一个原始对象添加动画可参见p285页的方法2;
7.3.5 属性动画的工作原理
属性动画要求动画作用的对象提供该属性的set方法,属性动画根据你传递的该属性的初始值和最终值,以及动画的效果多次去掉用set方法。每次 传递给set方法的值都是不一样的,确切来说是随着时间的推移,所传递的值越来越接近最终值。如果动画的时候没有传递初始值,那么还要提供get方法,因 为系统要去获取属性的初始值。
7.4 使用动画的注意事项
注 意View动画是对View的影像做动画,并不是真正改变View的状态,因此有时候会出现动画完成后View无法隐藏的现象,即 setVisibility(View.GONE)失效了,这个时候只要调用view.clearAnimation()清除View动画即可解决此问 题。
将View移动(平移)后,在Android3.0以前的系统上,不管是View动画还是属性动画,新位置均无法触发单击事件,同时,老位置仍 然可以触发单击事件。尽管View已经在视觉上不存在了,将View移回原位置以后,原位置的单击事件继续生效。从3.0开始,属性动画的单击事件触发位 置为移动后的位置,但是View动画仍然在原位置。
关于Android开发艺术探索学习笔记(七)就给大家介绍这么多,后续还会持续更新android艺术探索相关知识,请大家持续关注本站,谢谢。