动画-补间动画、属性动画、帧动画

2,683 阅读10分钟

Android 动画

动画有很多种,我们常见的是有3种,分为视图动画(又称为补间动画)、帧动画、属性动画.
可参考以下文章系列
Android 逐帧动画:关于 逐帧动画 的使用都在这里了!
Android:这是一份全面 & 详细的补间动画使用教程
Android 动画:手把手教你使用 补间动画 (视图动画)
Android 属性动画:这是一篇很详细的 属性动画 总结&攻略
Android ObjectAnimator类:手把手带你自定义属性动画
Android 动画:你真的会使用插值器与估值器吗?(含详细实例教学)
Android自定义View:手把手带你深入了解神秘的估值器(TypeEvaluator)

Android 中的动画有三种类型:
View Animation(补间动画):只能设置给View,可以进行位置,大小,旋转,透明四种变化。(xml = anim)
Drawable Animation(帧动画):用来一个个的显示图片资源,类似于幻灯片一帧一帧地播放。(xml = drawable)
Property Animation(属性动画):Android3.0以上系统中使用,这种动画可以设置给任何object并且是可以扩展的,可以自定义任何类型和属性的动画。(xml = animator)
View Animation(补间动画):
补间动画可以对View进行位置,大小,旋转,透明度四种变化,但是值得注意的是补间动画并没有真正改变View的属性,也就是说一个Button 进行位移动画,则位移之后的位置并不能响应这个Button的点击事件,而在Button的初始位置才能响应Button的点击事件。

1.帧动画 Drawable Animation

1.1 定义

Drawable 动画其实就是 Frame 动画(帧动画),它允许你实现像播放幻灯片一样的效果,这种动画的实质其实是 Drawable, 所以这种动画的 XML 定义方式文件一般放在 res/drawable/ 目录下。

1.2 Drawable 动画详细说明

我们依旧可以使用 xml 或者 java 方式实现帧动画。但是依旧推荐使用 xml,具体如下:

<animation-list> 必须是根节点,包含一个或者多个<item>元素,属性有:

  • android:oneshot true 代表只执行一次,false 循环执行。
  • <item> 类似一帧的动画资源。

<item> animation-list 的子项,包含属性如下:

  • android:drawable 一个 frame 的 Drawable 资源。
  • android:duration 一个 frame 显示多长时间。

1.3 Drawable 动画实例演示

关于帧动画相对来说比较简单,这里给出一个常规使用框架,如下:

<!-- 注意:rocket.xml文件位于res/drawable/目录下 -->
<?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="@[package:]drawable/drawable_resource_name"
        android:duration="integer" />
</animation-list>

使用:

ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);

rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
rocketAnimation.start();

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

2.视图动画(补间动画)

2.1定义

视图动画,也叫 Tween (补间)动画可以在一个视图容器内执行一系列简单变换(位置、大小、旋转、透明度)。补间动画通过 XML 或 Android 代码定义,建议使用 XML 文件定义,因为它更具可读性、可重用性

2.2视图动画分类

java 类名xml 关键字描述信息
AlphaAnimation<alpha> 放置在 res/anim/ 目录下渐变透明度动画效果
RotateAnimation<rotate> 放置在 res/anim/ 目录下画面转移旋转动画效果
ScaleAnimation<scale> 放置在 res/anim/ 目录下渐变尺寸伸缩动画效果
TranslateAnimation<translate> 放置在 res/anim/ 目录下画面转换位置移动动画效果
AnimationSet<set> 放置在 res/anim/ 目录下一个持有其它动画元素 alpha、scale、translate、rotate 或者其它 set 元素的容器
通过上图和上表可以直观的看出来补间动画的关系及种类了,接下来我们就详细一个一个的介绍一下各种补间动画。

2.3视图动画类型详解

2.3-1 动画基类Animation

可以看出来 Animation 抽象类是所有补间动画类的基类,所以基类会提供一些通用的动画属性方法,如下我们就来详细看看这些属性,。
对应的属性详解

xml 属性java 方法解释
android:detachWallpapersetDetachWallpaper(boolean)是否在壁纸上运行
android:durationsetDuration(long)动画持续时间,毫秒为单位
android:fillAftersetFillAfter(boolean)控件动画结束时是否保持动画最后的状态
android:fillBeforesetFillBefore(boolean)控件动画结束时是否还原到开始动画前的状态
android:fillEnabledsetFillEnabled(boolean)与android:fillBefore效果相同
android:interpolatorsetInterpolator(Interpolator)设定插值器(指定的动画效果,譬如回弹等)
android:repeatCountsetRepeatCount(int)重复次数
android:repeatModesetRepeatMode(int)重复类型有两个值,reverse表示倒序回放,restart表示从头播放
android:startOffsetsetStartOffset(long)调用start函数之后等待开始运行的时间,单位为毫秒
android:zAdjustmentsetZAdjustment(int)表示被设置动画的内容运行时在Z轴上的位置(top/bottom/normal),默认为normal

2.3-2 Alpha 属性详解

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

2.3-3 Rotate 属性详解

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

2.3-4. Scale 属性详解

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

2.3-5. Translate 属性详解

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

2.3-6. AnimationSet 详解

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

2.3视图动画使用

通过上面对于动画的属性介绍之后我们来看看在 Android 中这些动画如何使用(PS:这里直接演示 xml 方式,至于 java 方式太简单了就不说了),如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@[package:]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"
        android:pivotY="float" />
    <translate
        android:fromXDelta="float"
        android:toXDelta="float"
        android:fromYDelta="float"
        android:toYDelta="float" />
    <rotate
        android:fromDegrees="float"
        android:toDegrees="float"
        android:pivotX="float"
        android:pivotY="float" />
    <set>
        ...
    </set>
</set>

使用:

ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);

上面就是一个标准的使用我们定义的补间动画的模板。至于补间动画的使用,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 动画

到此整个 Android 的补间动画常用详细属性及方法全部介绍完毕

2.4 视图动画 Interpolator 插值器详解

其实各种插值器都是实现了 Interpolator 接口而已,同时可以看见系统提供了许多已经实现 OK 的插值器, 具体如下:

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新增,定义路径坐标后按照路径坐标来跑。

2.5 插值器使用方法

插值器的使用比较简答,如下:

<set android:interpolator="@android:anim/accelerate_interpolator">
    ...
</set>

2.6 插值器的自定义

有时候你会发现系统提供的插值器不够用,可能就像 View 一样需要自定义。所以接下来我们来看看插值器的自定义, 关于插值器的自定义分为两种实现方式,xml 自定义实现(其实就是对现有的插值器的一些属性修改)或者 java 代码实现方式。如下我们来说说。

先看看 XML 自定义插值器的步骤:

  1. 在 res/anim/ 目录下创建 filename.xml 文件。

  2. 修改你准备自定义的插值器如下:

     <?xml version="1.0" encoding="utf-8"?>
     <InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android"
         android:attribute_name="value"
         />
    
  3. 在你的补间动画文件中引用该文件即可。

可以看见上面第二步修改的是现有插值器的一些属性,但是有些插值器却不具备修改属性,具体如下:

无可自定义的 attribute。

android:factor 浮点值,加速速率(默认值为1)。

android:tension 浮点值,起始点后拉的张力数(默认值为2)。

android:tension 浮点值,起始点后拉的张力数(默认值为2)。 android:extraTension 浮点值,拉力的倍数(默认值为1.5)。

无可自定义的 attribute。

android:cycles 整形,循环的个数(默认为1)。

android:factor 浮点值,减速的速率(默认为1)。

无可自定义的 attribute。

android:tension 浮点值,超出终点后的张力(默认为2)。

再来看看 Java 自定义插值器的(Java 自定义插值器其实是 xml 自定义的升级,也就是说如果我们修改 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;
    }
    ......
}

到此整个补间动画与补间动画的插值器都分析完毕了。

3. 属性动画 Property Animation

这就直接参考郭神的三篇大作了Android属性动画完全解析(上),初识属性动画的基本用法