Android Animation之补间动画

来源:互联网 发布:淘宝基础班导航条全屏 编辑:程序博客网 时间:2024/06/09 14:26

Android Animation之补间动画

转载请注明:
http://blog.csdn.net/sinat_30276961/article/details/49721207

最近工作忙,导致博客都给荒废了,罪过罪过~今天开始,尽量继续写吧。好,今天我要温故的主题是–Android的Animation里的补间动画。

Animation

说到Android的Animation,其实大体可以分为三种:帧动画、补间动画和属性动画。

帧动画归纳起来不复杂:准备一堆图片素材,然后用animation-list进行排布,最后用AnimationDrawable去展示就行。

补间动画相比较帧动画,就显得复杂、多变许多。至于属性动画,我会在后面再做总结。

补间动画

好了,说了这么多,那到底什么是补间动画?补间动画,顾名思义,就是补充中间的动画部分。也就是说,动画起始和动画结束都已经确定,所需要的是中间的不断变化的动画。

那么,Android是怎么实现补间动画的呢?Android端现成的共有四种补间动画:alpha、scale、translate和rotate。实现方式有两种:xml里定义动画和代码里创建动画。

xml定义

首先来讲下xml里补间动画的创建方式。首先,你需要在工程的res下创建一个anim文件夹,用于放置动画xml文件。
然后创建文件,比方说,res/anim/alpha.xml

<?xml version="1.0" encoding="utf-8"?><alpha xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="3000"    android:fromAlpha="1"    android:toAlpha="0"    android:repeatCount="10"    android:repeatMode="reverse"></alpha>

这里,可以用到的属性很多,大家要学会见文猜意,很多都很容易明白。比方说上面的duration是指动画执行时间;fromAlpha和toAlpha是透明度的起始和结束值;repeatCount是指重复次数;repeatMode=”reverse”可以认为是从定义的方向变化和反方向变化交替执行。

ok,来看看执行效果:
这里写图片描述

再来看看scale

<?xml version="1.0" encoding="utf-8"?><scale xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="2000"    android:fillAfter="true"    android:fromXScale="1"    android:toXScale="1.5"    android:fromYScale="1"    android:toYScale="1.5"    android:pivotX="0"    android:pivotY="0">    <!-- pivotX和pivotY带上%指的是自己左边缘或者顶端开始的相对自己长宽的百分比偏移所在的锚点位置;        加上%p代表相对与parent长宽的百分比偏移所在的锚点位置;        不带任何的,代表自身左边缘或者顶端开始的像素偏移所在的锚点位置        ...Scale指的是相对于自身的缩放比例--></scale>

这里,先说说fillBefore和fillAfter这两个属性。这两个属性的含义可以算是刚好相反。fill意为填满、固定,后面的before和after意为是起始还是结束。也就是说,fillBefore意思是固定在起始画面;fillAfter为固定在结束画面。
默认情况下,fillBefore = true,fillAfter = false。也就是说,最后,动画结束,会退回到最初状态。
这个不用太过于深究,只要记住,fillAfter常常是要用到的,目的是为了最后保持在结束动画。不过,虽然那个view动画结束后移位了或怎么样,但事实上,它还是在原先定义的位置。所以,实际使用时需要注意这点。当然,如果你使用的是属性动画,那么你就不用顾虑这些了。因为那个view是真的到了结束的那个状态了。

这里,有个锚点位置定义的属性,由pivot打头。这个有三种定义锚点的方式,我在xml里也注释了,就不多说了。
其他的属性也没什么好讲,很清晰。

注意,这里定义了fillAfter=true,所以最后会停在结束一帧上。
这里写图片描述
如果没有这个属性,那么动画结束,会自动跳回到起始一帧上。

接着来看看translate animation。

<translate xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="3000"    android:fromXDelta="0"    android:toXDelta="100%"    android:fromYDelta="0"    android:toYDelta="100%"    android:repeatCount="10"    android:repeatMode="reverse">    <!--这里...Delta后面带上%,代表相对与自己宽度和高度的百分比距离;        不带%,就代表移动的像素距离;        带%p,代表相对于parent的宽度和高度的百分比距离--></translate>

…Delta结尾的属性,代表移动的起始偏移和结束偏移值。这里的定义方式和上面的pivot定义方式类似:带%是代表相对于自己的比例;不带%,就是纯粹的像素距离;带%p则代表相对于parent的比例。
效果图就不上了,最后会附上代码,有兴趣的朋友可以下下来。

最后是rotate animation。

<rotate xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="3000"    android:repeatMode="reverse"    android:repeatCount="10"    android:fromDegrees="0"    android:toDegrees="360"    android:pivotY="50%"    android:pivotX="50%">    <!-- pivotX和pivotY带上%指的是相对自己左边缘或者顶端开始的百分比偏移所在的锚点位置;        加上%p代表相对与parent的百分比偏移所在的锚点位置;        不带任何的,代表自身左边缘或者顶端开始的像素偏移所在的锚点位置 --></rotate>

锚点的定义和scale一致,其余的属性差不多,我就不赘述了。fromDegrees和toDegrees代表起始和结束角度。

代码定义

接下去,稍微来看看代码定义动画的方式。

new AlphaAnimation(1, 0);new ScaleAnimation(1, 1.5f, 1, 1.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 200);new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

这里,我把四种动画的定义方式直接先贴出来了,因为它们都继承自Animation,所以很多设置都是一致的,除了初始化相关的属性。
比方说Animation.setDuration、Animation.setFillAfter等等等等这些都是一致的。

ok,我贴一下它们的初始化:

AlphaAnimation (float fromAlpha, float toAlpha)ScaleAnimation (float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)TranslateAnimation (int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)RotateAnimation (float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

看这部分时,可以对照着看xml里定义的属性,其实是一样的。Alpha就不说了。
Scale里的前面四个参数定义起始和结束的x和y的比例变化。后面四个参数定义x方向和y方向相对于哪个锚点进行缩放比例。这里也分为相对于自己,相对于parent和相对于像素。
如下代码所示:

    /**     * The specified dimension is an absolute number of pixels.     */    public static final int ABSOLUTE = 0;    /**     * The specified dimension holds a float and should be multiplied by the     * height or width of the object being animated.     */    public static final int RELATIVE_TO_SELF = 1;    /**     * The specified dimension holds a float and should be multiplied by the     * height or width of the parent of the object being animated.     */    public static final int RELATIVE_TO_PARENT = 2;

代码部分定义其实不难,多去看看api就知道了。

插值器

最后,我来讲讲插值器。什么是插值器呢?插值器实际上就是补间动画的真正精髓所在。上面讲过,补间动画就是补上中间的变化,那么这个变化的值从何而来呢,就是插值器那里获得的。

那么就会有朋友提出疑问,上面很多动画都实现了,也没见到什么插值器啊!呵呵,其实它默认会自己放一个插值器上去的。

    /**     * Gurantees that this animation has an interpolator. Will use     * a AccelerateDecelerateInterpolator is nothing else was specified.     */    protected void ensureInterpolator() {        if (mInterpolator == null) {            mInterpolator = new AccelerateDecelerateInterpolator();        }    }

下面贴出google实现的一些插值器:
这里写图片描述

可以看到,google给我们提供了9个插值器。这些插值器基本上能满足我们日常的开发需要了。比方说,弹球效果适合球落地回弹,也适合一些东西的展示,如dialog,会有震颤感。

部分插值器还提供了一些属性用于设置它的程度,比方说AccelerateInterpolator

    /**     * Constructor     *     * @param factor Degree to which the animation should be eased. Seting     *        factor to 1.0f produces a y=x^2 parabola. Increasing factor above     *        1.0f  exaggerates the ease-in effect (i.e., it starts even     *        slower and ends evens faster)     */    public AccelerateInterpolator(float factor) {        mFactor = factor;        mDoubleFactor = 2 * mFactor;    }

factor代表加速速率,默认为1。

其余属性代表的含义如下所示:
accelerateDecelerateInterpolator

accelerateInterpolator
android:factor 浮点值,加速速率,默认为1
anticipateInterploator
android:tension 浮点值,起始点后退的张力、拉力数,默认为2
anticipateOvershootInterpolator
android:tension 同上
android:extraTension 浮点值,拉力的倍数,默认为1.5(2 * 1.5)
bounceInterpolator

cycleInterplolator
android:cycles 整数值,循环的个数,默认为1
decelerateInterpolator
android:factor 浮点值,减速的速率,默认为1
linearInterpolator

overshootInterpolator
浮点值,超出终点后的张力、拉力,默认为2

如果上述这些还不能让你满意,那么你可以用自定义Interpolator来实现你自己的插值器。

/** * An interpolator defines the rate of change of an animation. This allows * the basic animation effects (alpha, scale, translate, rotate) to be  * accelerated, decelerated, repeated, etc. */public interface Interpolator extends TimeInterpolator {    // A new interface, TimeInterpolator, was introduced for the new android.animation    // package. This older Interpolator interface extends TimeInterpolator so that users of    // the new Animator-based animations can use either the old Interpolator implementations or    // new classes that implement TimeInterpolator directly.}

可以看到Interpolator继承自TimeInterpolator。

public interface TimeInterpolator {    /**     * Maps a value representing the elapsed fraction of an animation to a value that represents     * the interpolated fraction. This interpolated value is then multiplied by the change in     * value of an animation to derive the animated value at the current elapsed animation time.     *     * @param input A value between 0 and 1.0 indicating our current point     *        in the animation where 0 represents the start and 1.0 represents     *        the end     * @return The interpolation value. This value can be more than 1.0 for     *         interpolators which overshoot their targets, or less than 0 for     *         interpolators that undershoot their targets.     */    float getInterpolation(float input);}

进去后看到一个接口,那就是getInterpolation。从它的注释可以看到,input是一个从0到1变化的值,返回的就是插值。也就是说,我们通过input这个值,进行一定的数学公式的转换,最后得到插值就行了,是不是很简单呢。

我们随便看个AccelerateInterpolator 加速度插值器

    public float getInterpolation(float input) {        if (mFactor == 1.0f) {            return input * input;        } else {            return (float)Math.pow(input, mDoubleFactor);        }    }

当factor值为1.0f时,动画加速轨迹相当于一条y=x^2的抛物线。如下图:
这里写图片描述
当factor不为1时,轨迹曲线是y=x^(2*fractor)的曲线。
示例:当fractor为4时,插值器的加速轨迹曲线如下图:
这里写图片描述

当然上面这些插值器的效果也可以通过组合动画来进行实现。

组合动画

那么什么是组合动画呢?组合动画就是通过一堆动画各种组合方式组合起来所形成的。

组合的属性有很多,归纳起来如下:
1. 动画间的一起或延时开始的先后顺序。
2. 各种类型动画组合起来,共用插值器或者各自使用自己的插值器。

如上面的弹球效果插值器可以通过组合多个translate动画来实现。
组合动画给我们提供了更多的创造空间,我们可以发挥想象,任意组合。而且组合的先后顺序也会影响整个动画效果。比方说,先添加相对自己的中心点旋转再添加移动 和 先添加移动再添加旋转 这两个的动画效果截然不同。

说了这么多,那么怎么实现组合呢?
在xml里,我们要用到的是< set >属性;而在代码端,我们要用到的是AnimationSet。
AnimationSet本身也是继承自Animation,这就类似于View,你可以把AnimationSet理解为ViewGroup。
用到的接口和属性基本都继承Animation,所以很容易上手,这里就不再赘述了。

最后,需要源码的朋友点击:代码入口

1 0
原创粉丝点击