动画

动画类型

  在Android动画中,共有两种类型的动画:View Animation(视图动画)和Property Animation(属性动画)。其中,View Animation包括Tween Animation(补间动画)和Frame Animation(逐帧动画);Property Animation包括ValueAnimator和ObjectAnimator.

  • View Animation(视图动画、Tween动画、补间动画):在最早的版本中就已经提供了,只能被用来设置View的动画,用到的xml文件放在res/anim目录下,访问时使用R.anim.xxx。也可以放在res/drawable文件夹下,访问时使用R.drawable.xxx。补间动画创建的是Animation
  • Drawable Animation(Frame动画、帧动画):用来一个一个地显示Drawable的resources,就像放幻灯片一样,其实可以划分到视图动画的类别,用到的图片资源放在res/drawable目录下,帧动画创建的是AnimationDrawable
  • Property Animation(属性动画):只对Android 3.0以上版本才有效,这种动画可以设置给任何Object,包括那些还没有渲染到屏幕上的对象。这种动画是可扩展的,可以让你自定义任何类型和属性的动画,用到的xml文件放在res/animator目录下,属性动画创建的是Animator

1.View Animation(视图动画、补间动画)

具体用到的类

java类名 xml关键字 描述信息
AlphaAnimation <alpha> 渐变透明度动画效果
RotateAnimation <rotate> 画面旋转动画效果
ScaleAnimation <scale> 尺寸伸缩动画效果
TranslateAnimation <translate> 移动动画效果

Animation抽象类是所有视图动画的基类,所以基类会提供一些通用的动画属性方法,如下所示:

xml属性 java方法 解释
android:detachWallpaper setDetachWallpaper(boolean) 是否在壁纸上运行
android:duration setDuration(long) 动画持续时间,毫秒为单位
android:fillAfter setFillAfter(boolean) 控件动画结束时是否保持动画最后的状态
android:fillBefore setFillBefore(boolean) 控件动画结束时是否还原到开始动画前的状态
android:fillEnabled setFillEnabled(boolean) 与android:fillBefore效果相同
android:interpolator setInterpolator(Interpolator) 设置插值器(指定的动画效果,如回弹等)
android:repeatCount setRepeatCount(int) 重复次数
android:repeatMode setRepeatMode(int) 重复类型有两个值,reverse表示倒序回放,restart表示从头播放
android:startOffset setStartOffset(long) 调用start函数之后等待开始运行的时间,单位为毫秒
android:zAdjustment setZAdjustment(int) 表示被设置动画的内容运行在Z轴上的位置(top

以上属性,每种视图动画都具备这些属性,接下来是每种视图动画的特有属性:
(1).Alpha特有属性:

xml属性 java方法 解释
android:fromAlpha AlphaAnimation(float fromAlpha,...) 动画开始的透明度(0.0-1.0,0.0是全透明,1.0是不透明)
android:toAlpha AlphaAnimation(...,float toAlpha) 动画结束的透明度,同上

(2).Rotate特有属性:

xml属性 java方法 解释
android:fromDegrees RotateAnimation(float fromDegrees,...) 旋转开始角度,正代表顺时针度数,负代表逆时针度数
android:toDegrees RotateAnimation(...,float toDegrees,...) 旋转结束角度,正代表顺时针度数,负代表逆时针度数
android:pivotX RotateAnimation(...,float pivotX,...) 缩放起点X坐标(数值、百分数、百分数p,比如50表示当前View左上角坐标家50px为起始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY RotateAnimation(...,float pivotY) 缩放起点Y坐标,同上

(3).Scale特有属性:

xml属性 java方法 解释
android:fromXScale ScaleAnimation(float fromX,...) 初始X轴缩放比例,1.0表示无变化
android:toXScale ScaleAnimation(...,float toX,...) 结束X轴缩放比例
android:fromYScale ScaleAnimation(...,float fromY,...) 初始Y轴缩放比例
android:toYScale ScaleAnimation(...,float toY,...) 结束Y轴缩放比例
android:pivotX ScaleAnimation(...,float pivotX,...) 缩放起点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY ScaleAnimation(...,float pivotY) 缩放起点Y轴坐标,同上

(4).Translate特有属性:

xml属性 java方法 解释
android:fromXDelta TranslateAnimation(float fromXDelta,...) 起始点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:fromYDelta TranslateAnimation(...,float fromYDelta,...) 起始点Y轴坐标,同上
android:toXDelta TranslateAnimation(...,float toXDelta,...) 结束点X轴坐标,同上
android:toYDelta TranslateAnimation(...,float toYDelta) 结束点Y轴坐标,同上

AnimationSet继承自Animation,是上面四种的组合容器管理类,没有自己特有的属性,它的属性继承自Animation,所以,当我们对<set>标签使用Animation的属性时,会对该标签下的所有子控件都产生影响。

视图动画的举例:

//动画的xml文件;
<alpha
    android:duration="2000"
    android:fromAlpha="1.0"
    android:toAlpha="0.1" />
//开始动画;
Animation animationAlpha = AnimationUtils.loadAnimation(this, R.anim.alpha_anim);
mImageView.startAnimation(animationAlpha);
//取消动画;
mImageView.clearAnimation(animationAlpha);

Animation还有如下常用的方法:

Animation类的方法 解释
reset() 重置Animation的初始化
cancel() 取消Animation动画
start() 开始Animation动画
setAnimationListener(AnimationListener listener) 给当前Animation设置动画监听
hasStarted() 判断当前Animation是否开始
hasEnded() 判断当前Animation是否结束

视图动画只能给View使用,那么View中和动画相关的常用方法如下:

View类的常用动画操作方法 解释
startAnimation(Animation animation) 对当前View开始设置Animation动画
clearAnimation() 取消对View在执行的Animation动画

特别注意事项:视图动画执行之后并未改变View的真实布局属性值,切记这一点。譬如我们在Activity中有一个Button在屏幕上方,我们设置了平移动画移动到屏幕下方然后保持动画最后执行状态呆在屏幕下方,这时如果点击屏幕下方动画执行之后的Button是没有任何反应的,而点击原来屏幕上方没有Button的地方却响应的是点击Button的事件。就是说执行完视图动画后,View依旧是执行动画之前的状态和位置。

注意事项
(1).使用<set>做为xml动画文件的跟标签时,设置repeatCount="infinite"时,是无效的,但是把这个属性放在<set>下面的具体的动画标签中就可以实现了,如放在<alpha>标签中;
(2).duration的时间包含了startOffset的时间,比如duration设置为2000,startOffset设置为1000,那么实际动画时间只有duration-startOffset=1000;

插值器Interpolator

  • 作用是可以控制动画的变化速率,可以通过 @android:anim 来选择不同的插值器。系统已经实现了许多插值器,如下:
java类 xml id值 描述
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 动画始末速率较慢,中间加速
AccelerateInterpolator @android:anim/accelerate_interpolator 动画开始速率较慢,之后慢慢加速
AnticipateInterpolator @android:anim/anticipate_interpolator 开始的时候从后向前甩
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 类似上面的AnticipateInterpolator
BounceInterpolator @android:anim/bounce_interpolator 动画结束时弹起
CycleInterpolator @android:anim/cycle_interpolator 循环播放速率改变为正弦曲线
DecelerateInterpolator @android:anim/decelerate_interpolator 动画开始块然后慢
LinearInterpolator @android:anim/linear_interpolator 动画匀速改变
OvershootInterpolator @android:anim/overshoot_interpolator 向前弹出一定值之后回到原来位置
PathInterpolator 新增,定义路径坐标后按照路径来跑
//插值器在xml使用;
<set android:interpolator="@android:anim/accelerate_interpolator">
    ...
</set>
  • 自定义插值器:
      插值器的自定义分为两种实现方式,xml自定义实现(其实就是对现有的插值器的一些属性修改)或者javav代码实现; xml自定义插值器: (1).在res/anim目录下创建xxx.xml文件;
    (2).修改准备自定义跌插值器;
<?xml version="1.0" encoding="utf-8"?>
<InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android"
    android:attribute_name="value"
    />

(3).在视图动画文件中引用该文件即可;
修改现有插值器的一些属性,但是有些插值器却不具备修改属性,具体如下:

插值器 备注
<accelerateDecelerateInterpolator> 无可自定义的attribute
<accelerateInterpolator> android:factor 浮点值,加速速率(默认值为1)
<anticipateInterploator> android:tension 浮点值,起始点后拉的张力数(默认值为2)
<anticipateOvershootInterpolator> android:tension 浮点值,起始点后拉的张力数(默认值为2)。android:extraTension 浮点值,拉力的倍数(默认值为1.5)。
<bounceInterpolator> 无可自定义的attribute。
<cycleInterplolator> android:cycles 整形,循环的个数(默认为1)。
<decelerateInterpolator> android:factor 浮点值,减速的速率(默认为1)。
<linearInterpolator> 无可自定义的attribute。
<overshootInterpolator> android:tension 浮点值,超出终点后的张力(默认为2)。

java代码实现插值器:java自定义插值器其实算是插值器的升级,也就是说如果我们修改xml属性还不能满足需求,那就可以选择通过java代码来实现;
  所有的Interpolator都实现了Interpolator接口,而Interpolator接口又继承自 TimeInterpolator,TimeInterpolator接口定义了一个float getInterpolation(float input);方法,这个方法是由系统调用的,其中的参数input代表动画的时间,在0和1之间,也就是开始和结束之间。
  如下是一个动画始末速率较慢、中间加速的AccelerateDecelerateInterpolator插值器:

public class AccelerateDecelerateInterpolator extends BaseInterpolator
        implements NativeInterpolatorFactory {
    ......
    public float getInterpolation(float input) {
        return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
    }
    ......
}

2.Drawable Animation(帧动画)

  这种动画的实质是Drawable,所以这种动画的xml定义文件一般放在res/drawable目录下。
xml文件中的属性:
<animation-list> 必须是根节点,包含一个或者多个<item>元素,属性有:android:oneshot (true代表只执行一次,false循环执行。)
<item> 类似一帧的动画资源。
<item> animation-list的子项,包含属性如下:android:drawable 一个frame的Drawable资源。
android:duration 一个frame显示多长时间。
  在给ImageView设置动画资源时,有两种方法,既可以通过android:src实现,也可以通过android:background实现。
  实现逐帧动画,需要先拿到ImageView中所设置的动画资源,然后利用AnimationDrawable的start()方法开始逐帧动画。当通过android:src设置动画资源时,对应的取出方式是mImageView.getDrawable();如果通过Android:background设置动画资源时,对应的取出方式是mImageView.getBackground();

//xml动画文件;
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true"
    >
    <item android:drawable="@mipmap/ic_launcher" android:duration="1000"/>
    <item android:drawable="@mipmap/icon_scrollbar" android:duration="1000"/>
    <item android:drawable="@mipmap/ic_launcher_round" android:duration="1000"/>
</animation-list>
//java代码执行;
mImageView.setBackgroundResource(R.drawable.drawable_anim);
AnimationDrawable animationDrawable = (AnimationDrawable)mImageView.getBackground();
animationDrawable.start();

特别注意:如果AnimationDrawable的start()方法不能在Activity的onCreate方法中调运,因为AnimationDrawable还未完全附着到window上,所以最好的调运时机是onWindowFocusChanged()方法中。

3.Property Animation(属性动画)

属性动画的原理就是修改控件的属性值;
属性动画中的几个常用类的之间关系:

关系 xml关键字 解释
Animator extends Object
AnimatorSet extends Animator <set>放置在res/animator/目录下 动画集合
ValueAnimator extends Anitator <animator>放置在res/animator/目录下 在一个特定的时间里执行一个动画
ObjectAnimator extends ValueAnimator <objectAnimator>放置在res/animator/目录下 一个对象的一个属性动画
TimeAnimator extends ValueAnimator 不支持xml 时序监听回调工具
FakeAnimator @hide
RenderNodeAnimator @hide
RevealAnimator @hide
  • <set>标签:
xml属性 解释
android:ordering 控制子动画启动方式时先后有序还是同时进行。sequentially:动画按照先后顺序,together(默认):动画同时启动;
  • <objectAnimator>标签:
xml属性 解释
android:propertyName String类型,必须要设置的节点属性,代表要执行动画的属性(通过名字引用),辟如你可以指定了一个View的”alpha” 或者 “backgroundColor” ,这个objectAnimator元素没有对外说明target属性,所以你不能在XML中设置执行这个动画,必须通过调用 loadAnimator()方法加载你的XML动画资源,然后调用setTarget()应用到具备这个属性的目标对象上(譬如TextView)。
android:valueFrom float、int或者color类型,动画的起始点,如果没有指定,系统会通过属性的get方法获取,颜色也是6位十六进制的数字表示。
android:valueTo float、int或者color类型,必须要设置的节点属性,表明动画结束的点;如果是颜色的话,由6位十六进制的数字表示。
android:duration 动画的时长,int类型,以毫秒为单位,默认为300毫秒。
android:startOffset 动画延迟的时间,从调用start方法后开始计算,int型,毫秒为单位。
android:repeatCount 一个动画的重复次数,int型,”-1“表示无限循环,”1“表示动画在第一次执行完成后重复执行一次,也就是两次,默认为0,不重复执行。
android:repeatMode 重复模式:int型,当一个动画执行完的时候应该如何处理。该值必须是正数或者是-1,“reverse”会使得按照动画向相反的方向执行,可实现类似钟摆效果。“repeat”会使得动画每次都从头开始循环。
android:valueType 关键参数,如果该value是一个颜色,那么就不需要指定,因为动画框架会自动的处理颜色值。有intType和floatType(默认)两种:分别说明动画值为int和float型。还有colorType和pathType;

在代码中使用动画:

  属性动画默认的时间是300毫秒;

Animator mAnimator = AnimatorInflater.loadAnimator(this, R.animator.alpha_animator);
mAnimator.setTarget(mImageView);
mAnimator.start();

注意事项

动画结束后控件没有消失

  使用下面两句代码来实现:

clearAnimation()
invalidate()