Android动画总结系列(2)——补间动画使用

来源:互联网 发布:用友软件集团招聘 编辑:程序博客网 时间:2024/05/17 07:13
一、综述
补间动画(Tween Animation、View Animation)是Android的基本动画之一,其与帧动画的本质完全不同。帧动画的原理是逐帧播放Drawable形成动画效果,补间动画是给出关键两帧,在两帧之间补充渐变的过程来实现动画效果。补充渐变来实现动画效果是动画的基本思想,这样看来,帧动画才属于另类,所以除非是完全无规律的动画效果,否则尽量不要使用帧动画。
Android支持的补间动画有四种:平移(Translate)、旋转(Rotate)、缩放(Scale)、透明度(Alpha),这四种效果涵盖了动画效果的基础。应用动画过程通常都不是简单的一个动画效果能搞定的,这时候我们需要使用动画集合(AnimationSet)来将以上四种效果灵活组合起来使用。
补间动画的应用对象是View。

二、xml用法
下文中X表示View布局距左位置,Y表示View布局距上位置,W表示View宽度,H表示View高度

2.1 平移动画
平移动画的本质就是将View的显示位置从某个位置(X0,Y0)移动到(X1,Y1)。注意这里说的显示位置,View在坐标系内的真实位置并未发生变化,所以动画的过程只会触发Draw过程,不会触发Measure过程。
动画开始前在红框位置的View,通过平移100%的动画后效果为绿色区域。

2.1.1 动画定义
动画定义res/anim/文件夹下。下例命名为tween_translate_animation_demo.xml
<translate    xmlns:android="http://schemas.android.com/apk/res/android"    android :fromXDelta="50%"    android :fromYDelta="50%"    android :toXDelta="100%"    android :toYDelta="100%"    android :fillAfter="true"    android:interpolator="@android:anim/decelerate_interpolator"    android :duration="1000"></translate>
fromXDelta:平移动画的初始帧时X的所在位置;50%表示动画起始于X + 50% * W 的位置
fromYDelta:平移动画的初始帧时Y的所在位置;50%表示动画起始于Y + 50% * H 的位置
toXDelta    :平移动画的结束帧时X的所在位置;100%表示动画结束于X + 100% * W 的位置
toYDelta    :平移动画的结束帧时Y的所在位置;100%表示动画结束于Y + 100% * H 的位置
fillAfter       : true表示动画结束后该动画被应用在界面上,也就是说,界面停留在动画最后一帧(上文的绿色View显示(X + W,Y + H)位置);false表示动画结束后,界面回到初始位置(上文的绿色View显示在X,Y位置)
interpolator: 动画的插值器,用于改变动画渐变过程的速率,常用的有:线性插值(linear_interpolator)、加速插值器(accelerate_interpolator)、减速插值器(decelerate_interpolator)、加减速插值器(accelerate_decelerate_interpolator)等。
duration     : 动画的持续时间

2.1.2 代码集成
首先是从XML中加载动画:
TranslateAnimation mTranslateAnimation = (TranslateAnimation) AnimationUtils.loadAnimation(this, R.anim.tween_translate_animation_demo );
将动画应用到View上:
mTxtViewFrameAnimationContainer .startAnimation(mTranslateAnimation);
结束动画:
mTxtViewFrameAnimationContainer .clearAnimation();

2.2 缩放动画
与平移动画相同的是,缩放动画也不改变View在布局中的位置,下图展示的缩放前的View(红色框内)与缩放后的View展示位置的对比:
上图是基于View(0,0)位置缩放到自身2倍大小的对比,可以看到View在父元素中并未改变位置,其改变的是draw方法的绘制区域。

2.2.1 动画定义
动画定义res/anim/文件夹下。下例命名为tween_scale_animation_demo.xml
<scale    xmlns:android="http://schemas.android.com/apk/res/android"    android :fromXScale="50%"    android :fromYScale="50%"    android :toXScale="200%"    android :toYScale="200%"    android :pivotX="10%"    android :pivotY="10%"    android :fillAfter="true"    android:interpolator="@android:anim/accelerate_decelerate_interpolator"    android :duration="1000"></scale>
fromXScale  : 缩放动画的初始帧中X轴的缩放比例;50%表示动画从50%W开始缩放
fromYScale  : 缩放动画的初始帧中Y轴的缩放比例;50%表示动画从50%H开始缩放
toXScale      : 缩放动画的结束帧中X轴的缩放比例;200%表示View的显示缩放到200%W大小,也就是宽度变大一倍
toYScale      : 缩放动画的结束帧中Y轴的缩放比例;200%表示View的显示缩放到200%H大小,也就是高度变大一倍
pivotX         : 缩放动画的X轴中心点(X轴心),表示动画以此点为中心开始缩放,10%表示以X+10%W为X轴重心
pivotY         : 缩放动画的Y轴中心点(Y轴心),表示动画以此点为中心开始缩放,10%表示以Y+10%H为Y轴重心
其他参数见2.1.1

2.2.2 代码集成
与平移动画完全相同,首先是从XML中加载动画:
ScaleAnimation mScaleAnimation = (ScaleAnimation) AnimationUtils.loadAnimation(this, R.anim.tween_scale_animation_demo );
将动画应用到View上:
mTxtViewFrameAnimationContainer .startAnimation(mScaleAnimation);
结束动画:
mTxtViewFrameAnimationContainer .clearAnimation();

2.3 旋转动画
旋转动画也不改变View在父布局的位置。如下图所示:
红色是View的布局位置,绿色为应用了旋转动画的显示位置。

2.3.1 动画定义
<rotate    xmlns:android="http://schemas.android.com/apk/res/android"    android :fromDegrees="180"    android :toDegrees="-270"    android :pivotX="10%"    android :pivotY="10%"    android :visible="true"    android :drawable="@mipmap/ic_launcher"    android :fillAfter="true"    android:interpolator="@android:anim/accelerate_decelerate_interpolator"    android :duration="1000"></rotate>
fromDegrees    : 旋转动画的初始帧时View的旋转角度,取值是整数,每360度是旋转一圈,180表示View从顺时针方向以中心点旋转180度作为动画起始位置
toDegrees        : 旋转动画的结束帧时View的旋转角度,取值是整数,-270表示View从逆时针方向以中心点旋转270度作为动画结束位置。fromDegrees > toDegrees则动画逆时针旋转,fromDegrees < toDegrees则动画顺时针旋转
pivotX              : 旋转动画的旋转中心点X坐标(轴点),表示动画以此点为中心旋转,10%表示动画以X+10%W为X中心点旋转
pivotY              : 旋转动画的旋转中心点Y坐标(轴点),表示动画以此点为中心旋转,10%表示动画以Y+10%H为Y中心点旋转
visible              : 设置动画的可见性,在xml中定义无效,true/false动画都照常运行
drawable         : 没找到作用
其他参数见2.1.1

2.3.2 代码集成
集成方式同上,加载动画:
RotateAnimation mRotateAnimation = (RotateAnimation) AnimationUtils.loadAnimation(this, R.anim.tween_rotate_animation_demo );
开始动画:
mTxtViewFrameAnimationContainer .startAnimation(mRotateAnimation);
结束动画:
mTxtViewFrameAnimationContainer .clearAnimation();

2.4 透明度动画
透明度动画只改变View显示的透明度,View的展示位置还是和View的布局位置重合的。

2.4.1 动画定义
<alpha    xmlns:android="http://schemas.android.com/apk/res/android"    android :fromAlpha="0.2"    android :toAlpha="1"    android :fillAfter="true"    android:interpolator="@android:anim/accelerate_decelerate_interpolator"    android :duration="1000"></alpha>
fromAlpha  : 透明度动画的初始帧时View的透明度,取值在0~1之间,小于0的等价于0,大于1的等价于1,0.2表示View初始透明度是0.2
toAlpha      : 透明度动画的结束帧时View的透明度,取值在0~1之间,小于0的等价于0,大于1的等价于1,1表示View初始透明度是1,也就是完全不透明
其他参数见2.1.1

2.4.2 代码集成
和上面三种动画完全相同,加载动画:
AlphaAnimation mAlphaAnimation = (AlphaAnimation) AnimationUtils.loadAnimation(this, R.anim.tween_alpha_animation_demo );
开始动画:
mTxtViewFrameAnimationContainer .startAnimation(mAlphaAnimation);
结束动画: 
mTxtViewFrameAnimationContainer .clearAnimation();

2.5 组合动画
一般要实现某种产品动画效果,上面谈到的四种基础动画都不是单独应用的,这时候我们可以通过动画组合将各种动画组装在一起执行,形成组合动画的效果。组合动画对应的Java类是AnimationSet。

2.5.1 动画定义
<set xmlns:android="http://schemas.android.com/apk/res/android"    android :duration="2000"    android :fillAfter="true"    android :fillBefore="true"    android :repeatMode="reverse"    android :shareInterpolator="true"    android:interpolator="@android:anim/accelerate_interpolator"    android :startOffset="1000">       <!--在此处添加translate、rotate 、scale、 alpha动画或者另一个set集合 --></set>
duration/fillAfter/interpolator前面都说过了,此处略。
fillBefore               : 标识在动画开始前,是否对View应用动画转化的效果。仅在mFillEnabled为true时有作用,否则其值默认为true
repeatMode          : repeatMode属性有两个取值:reverse和restart,表示动画重复时的执行策略,reverse反转动画到初始帧在继续执行,restart直接从结束帧调到初始帧执行。注意:reverse从结束帧到初始帧的执行也算一次动画执行,repeatCount为4的reverse模式则执行为,开始帧-->结束帧-->开始帧-->结束帧-->开始帧;restart则是开始帧-->结束帧循环4次。
shareInterpolator  : 标识各子动画是否应使用set中定义插值器,在set定义了插值器的情况下,true表示子动画应使用set定义插值器,false表示子动画可以使用自己的插值器。如果set没设置插值器,则此值没有作用
startOffset            : 表示动画集合何时开始执行,1000表示动画集合在1s后开始执行

2.5.2 代码集成
加载动画:
AnimationSet mAnimationSet = (AnimationSet) AnimationUtils.loadAnimation(this, R.anim.tween_animation_set_demo );
开始动画:
mTxtViewFrameAnimationContainer .startAnimation(mAnimationSet);
结束动画:
mTxtViewFrameAnimationContainer .clearAnimation();

三、代码实现

3.1 平移动画
mTranslateAnimation = new TranslateAnimation(TranslateAnimation. RELATIVE_TO_SELF, 0.5f ,        TranslateAnimation.RELATIVE_TO_SELF, 1f,        TranslateAnimation.RELATIVE_TO_SELF, 0.5f,        TranslateAnimation.RELATIVE_TO_SELF, 1f);mTranslateAnimation .setFillAfter(true);mTranslateAnimation .setInterpolator(new AccelerateDecelerateInterpolator());mTranslateAnimation .setDuration(1000);mTranslateAnimation .setAnimationListener(new Animation.AnimationListener() {    @Override    public void onAnimationStart(Animation animation) {        //动画开始执行时回调        Log. d("TEST11", "onAnimationStart");    }    @Override    public void onAnimationEnd(Animation animation) {        //动画结束执行时回调        Log. d("TEST11", "onAnimationEnd");    }    @Override    public void onAnimationRepeat(Animation animation) {        //动画重复执行时回调        Log. d("TEST11", "onAnimationRepeat");    }});
以上代码与之前的xml定义实现效果完全相同,并监听了动画执行的回调。
TranslateAnimation最常用的构造器是:
publicTranslateAnimation(intfromXType,float fromXValue,inttoXType, floattoXValue,
        int fromYType, float fromYValue,inttoYType, floattoYValue);
publicTranslateAnimation(floatfromXDelta,float toXDelta,floatfromYDelta, floattoYDelta);
第一个用的更多些,参数中的type可以取三种值:
TranslateAnimation.RELATIVE_TO_SELF:相对于自己宽高的取值,value的取值是float,值是期望位移值与宽/高的比值
TranslateAnimation.RELATIVE_TO_PARENT:相对于父元素的取值,取值为百分比
TranslateAnimation.ABSOLUTE:绝对值,平移的像素值,传入此参数,如果都传入此参数,则可以缩略为第二个构造器
代码集成与之前相同,见2.1.2,有关TranslateAnimation的其他属性设置后续再讨论。

3.2 缩放动画
mScaleAnimation = new ScaleAnimation(0.5f, 2f, 0.5f, 2f , 0.1f , 0.1f );mScaleAnimation.setFillAfter(true);mScaleAnimation.setInterpolator(new AccelerateDecelerateInterpolator());mScaleAnimation.setDuration(1000 );
ScaleAnimation的构造器有四个:
ScaleAnimation(Context context, AttributeSet attrs):动画从资源中加载,正常情况下用得比较少
ScaleAnimation( float fromX, float toX, float fromY, float toY):给定X轴的开始缩放比例结束缩放比例,Y轴开始缩放比例到Y轴缩放比例,构建一个缩放动画;fromX是动画开始时的水平缩放比例,toX是动画结束时的水平缩放比例,fromY是动画开始时的垂直缩放比例,toY是动画结束时的垂直缩放比例,比例值是相对于View宽高的,所以动画效果展示View的可视宽度从fromX * W缩放到toX*W,View可视高度从fromY * H缩放到toY * W;
ScaleAnimation( float fromX, float toX, float fromY, float toY, float pivotX, float pivotY):此接口与上一个接口的区别就在于指定了缩放中心点,缩放中心点前文已叙,此处不再展开。
ScaleAnimation( float fromX, float toX, float fromY, float toY,
  int pivotXType, float pivotXValue, int pivotYType, float pivotYValue):
pivotXType、pivotYType取值可以包括三种:
Animation.ABSOLUTE:表示后面的value是绝对位置,也就是说,如果两个type取值都是绝对值,则View按View坐标系的(pivotXValue, pivotYValue)为中心点缩放。pivotXValue=10,pivotYValue=10意味着View缩放中心点是(X+10, Y+10)
Animation.RELATIVE_TO_SELF:表示后面的value是相对位置,相对的是自己的宽高,取值是百分比,具体见2.2.1
Animation.RELATIVE_TO_PARENT:表示后面的value是相对父元素的宽高做中心点的,取值也是百分比
代码集成与之前相同,见2.2.2

3.3 旋转动画
mRotateAnimation = new RotateAnimation(-180, -90,        Animation.RELATIVE_TO_SELF, 0.1f,        Animation.RELATIVE_TO_SELF, 0.1f);mRotateAnimation.setFillAfter(true);mRotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());mRotateAnimation.setDuration(1000 );
RotateAnimation的构造方法:
RotateAnimation(Context context, AttributeSet attrs):从XML资源中解析动画
RotateAnimation( float fromDegrees, float toDegrees):取值解释见2.3.1
RotateAnimation( float fromDegrees, float toDegrees, float pivotX, float pivotY):中心点取值解释见3.2部分
RotateAnimation( float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue):中心点类型和取值见3.2,其他接口见下一篇文章。代码集成见2.3.2

3.4 透明度动画
mAlphaAnimation = new AlphaAnimation(0.2f, 1f);mAlphaAnimation.setFillAfter(true);mAlphaAnimation.setInterpolator(new AccelerateDecelerateInterpolator());mAlphaAnimation.setDuration(1000 );
AlphaAnimation的构造方法最简单,因为它没有中心点的概念:
AlphaAnimation(Context context, AttributeSet attrs):基于资源构造动画
AlphaAnimation( float fromAlpha, float toAlpha):fromAlpha是动画开始时的View的透明度,toAlpha是动画结束时View的透明度
代码集成见2.4.2

3.5 组合动画
mAnimationSet = new AnimationSet(false);mAnimationSet.setDuration(2000 );mAnimationSet.setFillAfter(true);mAnimationSet.setFillBefore(false);mAnimationSet.setRepeatMode(Animation.REVERSE);mAnimationSet.setInterpolator(new AccelerateInterpolator());mAnimationSet.setStartOffset(1000 );AlphaAnimation alphaAnimation = new AlphaAnimation(0.2f, 1f);alphaAnimation.setFillAfter(true );alphaAnimation.setInterpolator(new AccelerateInterpolator());alphaAnimation.setDuration(1000 );mAnimationSet.addAnimation(alphaAnimation);RotateAnimation rotateAnimation = new RotateAnimation(-180, -90,        Animation.RELATIVE_TO_SELF, 0.1f,        Animation.RELATIVE_TO_SELF, 0.1f);rotateAnimation.setFillAfter(true );rotateAnimation.setDuration(1000 );mAnimationSet.addAnimation(rotateAnimation);...
AnimationSet构造方法:
AnimationSet(Context context, AttributeSet attrs):通过资源定义构造对象
AnimationSet( boolean shareInterpolator):传入shareInterpolator标识,true标识所有的子动画都需要使用AnimationSet中定义的插值器,false标识各动画使用各自定义的插值器
其他接口作用见2.5.1,代码集成见2.5.2

四、源码分析
源码分析比较多,后面专门讨论。

五、兼容性
部分机型不兼容Alpha通道,导致透明度动画不执行

代码见https://qqliu10@bitbucket.org/qqliu10/androidtweenanimationdemo.git
0 0
原创粉丝点击