欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

android 动画详解之属性动画

程序员文章站 2022-03-17 13:56:27
...

动画的分类

在android3.0以前,android的动画机制比较简单,也可以说不健全,那时候是分为两种实现方式:帧动画和补间动画。
1. 帧动画说白了就像gif,在实现的过程中依赖一帧帧的图片资源,然后加载轮播
2. 补间动画倒是可以对view做一些简单的动态效果,但是功能过于简陋,只能够实现移动、缩放、旋转和淡入淡出这四种动画操作,局限性很大。
在3.0之后android提供了一个更加全面和强大的动画实现方式:属性动画。基于此我们可以实现各种各样的动画效果。当然前提你得会用….

一、属性动画的实现原理

属性动画的实现原理其实就是通过对值的不断操作。基于这个实现机制我们就可以在view的外层或内部对view进行持续性的更改操作已完成动画的效果。举个栗子吧:通过以下动画使button的透明度在3秒内从0匀速增至1

        ValueAnimator valueAnimator =  ValueAnimator.ofFloat(0f,1f);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
             button.setAlpha((float)animation.getAnimatedValue());
            }
        });
        valueAnimator.setDuration(3000);
        valueAnimator.start();

当然我们也可以通过setInterpolator()来设置值递增的加速度。

二、ObjectAnimator

ObjectAnimator是ValueAnimator的子类,也是我们用的比较多的个动画实现类。通过ObjectAnimator我们可以快速的实现上述效果:

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(button, "alpha",0f,1f);
objectAnimator.setDuration(3000);
objectAnimator.start();

这里就表示在3000毫秒内对button的alpha属性进行操作,使其值从0递增到1,从而实现button的透明值渐变动画。这里”alpha”表示对button的alpha属性进行操作,我们还可以传入”rotation”,”translationX”,”translationY”对view的旋转和位移进行动画表示。

三、组合动画

有时候单一的属性并不足以支撑我们的动画效果,这时候就需要使用组合动画,组合动画通过AnimatorSet将多个ObjectAnimator动画组合成一个动画集合进行展示。

        // 使按钮从左侧进入
        ObjectAnimator moveIn = ObjectAnimator.ofFloat(button, "translationX", -500f, 0f);
        moveIn.setDuration(2000);

        // 使按钮变为透明,再还原
        ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(button, "alpha",1f,0f,1f);
        alphaAnimator.setDuration(3000);

        // 使按钮旋转360°
        ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat(button, "rotation", 0f, 360f);
        rotationAnimator.setDuration(3000);

        // 组合上面三个动画
        AnimatorSet animators = new AnimatorSet();
        animators.play(alphaAnimator).with(rotationAnimator).after(moveIn);
        animators.start();

animatorSet有4个方法用以实现动画的组合逻辑,分别是:
1. after(Animator anim) 将现有动画插入到传入的动画之后执行
2. after(long delay) 将现有动画延迟指定毫秒后执行
3. before(Animator anim) 将现有动画插入到传入的动画之前执行
4. with(Animator anim) 将现有动画和传入的动画同时执行

after\before\with不光可以传入单一的属性动画, 也可以传入AnimatorSet组合动画。这样我们就能组合出特殊效果的动画了。

        // 垂直方向缩放大小
        ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(button,"scaleY",1f,3f,1f);
        scaleYAnimator.setDuration(3000);

        // 组合animators动画集合和scaleYAnaimator
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(animatorSet).with(scaleYAnimator);
        animatorSet.start();

四、动画监听

我们还可以监听动画在不同的节点的事件并执行相应的处理,比如开始动画、结束动画。Animator总共提供了4个监听事件如下:

animatorSet.addListener(new AnimatorListener() {  
    // 动画开始时执行
    @Override  
    public void onAnimationStart(Animator animation) {  
    }  

    // 动画重复的时候执行
    @Override  
    public void onAnimationRepeat(Animator animation) {  
    }  

   // 动画结束的时候执行
    @Override  
    public void onAnimationEnd(Animator animation) {  
    }  

    // 动画取消的时候执行
    @Override  
    public void onAnimationCancel(Animator animation) {  
    }  
});  

ObjectAnimator和AnimatorSet都是继承自Animator,所以他们都有AnimatorListener监听接口。很多时候我们并不会监听所有的事件,可能只会单独监听开始事件或者结束事件,我们可在这里传入实现了AnimatorListener的抽象类AnimatorListAdapter,然后选择性的实现AnimatorListener的某个或者多个事件。如下:

animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // do anything
            }
        });

五、Interpolator插值器

Interpolator主要是用来控制动画的变化率的,打个比方说,*落体运动,刚开始下落的速度为0,但是由于重力加速度导致其下落速度逐渐增大。Interpolator的作用就相当于重力加速度。现有系统提供了以下几种插值器:

1. LinearInterpolator(线性插值器):匀速动画。 

2. AccelerateDecelerateInterpolator(加速减速插值器):动画两头慢,中间快。 

3. DecelerateInterpolator(减速插值器):动画越来越慢。

4. BounceInterpolator(弹跳插值器):先加速至指向位置,然后反弹数次,逐渐停留至预定目标值。

5. CycleInterpolator(周期插值器):重复动画数次,依照正弦曲线的频率执行。

6. OvershootInterpolator:加速执行,会超出预定目标值,最火回至预定目标值。

7. AnticipateInterpolator:先反向执行,然后加速正向执行至目标值。

8. AnticipateOvershootInterpolator:先反向执行,然后加速正向执行, 会超出预定目标值,最后回至预定目标值。

动画未设置或者传入插值器为空,则默认采用LinearInterpolator插值器。

六、XML编写动画

我们就以最后一个组合的动画为例,采用xml进行编写实现。
xml代码如下:

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially" >
    <!--从左侧平移进入-->
    <objectAnimator
        android:duration="2000"
        android:propertyName="translationX"
        android:valueFrom="-500"
        android:valueTo="0"
        android:valueType="floatType" >
    </objectAnimator>

    <set android:ordering="together" >
        <!--旋转360度-->
        <objectAnimator
            android:duration="3000"
            android:propertyName="rotation"
            android:valueFrom="0"
            android:valueTo="360"
            android:valueType="floatType" >
        </objectAnimator>

        <set android:ordering="sequentially">
            <!--变透明,再还原-->
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="1"
                android:valueTo="0"
                android:valueType="floatType" >
            </objectAnimator>
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="0"
                android:valueTo="1"
                android:valueType="floatType" >
            </objectAnimator>
        </set>

    </set>
    <!--垂直方向放大,再还原-->
    <objectAnimator
        android:duration="1500"
        android:propertyName="scaleY"
        android:valueFrom="1"
        android:valueTo="3"
        android:valueType="floatType" >
    </objectAnimator>

    <objectAnimator
        android:duration="1500"
        android:propertyName="scaleY"
        android:valueFrom="3"
        android:valueTo="1"
        android:valueType="floatType" >
    </objectAnimator>
</set>
  1. 节点
    xml文件里共用了两个节点,分别是set、objectAnimator分别对应代码里的AnimatorSet和ObjectAnimator。那么他们的属性也就一目了然了。其中不一样的是xml配置的动画执行逻辑。
  2. 属性配置
    在代码里我们可通过with/after/before来配置其执行次序,但在xml里的先后顺序则是根据代码的先后顺序确定的,,也就是说xml里只有两种顺序关系,先后和同时。android:ordering=”sequentially”表示顺序执行,android:ordering=”together”表示同时执行。其他属性则可对应代码里设置方法。