Android动画机制与使用技巧(一)属性动画分析

来源:互联网 发布:淘宝永久封店怎么解封 编辑:程序博客网 时间:2024/05/16 04:33

在Android3.0之后,google就提出了属性动画,帮助开发者实现更丰富的动画效果

ObjectAnimator

ObjectAnimator是属性动画中最重要的实现类, 创建一个ObjectAnimator需要通过它的静态工厂类返回一个ObjectAnimator对象. 参数包括一个对象和对象的属性名字, 但这个属性必须要有set和get函数,内部会通过java反射机制来调用set函数修改对象属性值. 同样你也可以使用setInterpolator设置相应的插值器.

ObjectAnimator简单平移动画示例代码:

ObjectAnimator animator= ObjectAnimator.ofFloat(        view,"translationX",300);animator.setDuration(500);animator.start();

通过ObjectAnimator的静态工厂方法,创建一个ObjectAnimator对象。第一个参数自然是需要操纵的View,第二个参数则是要操纵的属性,而最后一个参数是一个可变数组参数,需要传进去该属性变化的一个取值过程,这里只设置了一个参数,即变化到300。当然,与视图动画一样,也可以给属性动画设置显示时长、差值器等属性,这些参数与在视图动画中的设置方法类似。

在使用ObjectAnimator的时候要操纵的属性必须具有get、set方法,不然ObjectAnimator就无法起效。下面是一些常用的可以直接使用属性动画的属性值。

  • translationX和translationY:这两个属性作为一种增量来控制着View对象从它布局容器的左上角坐标偏移的位置。
  • rotation、rotationX和rotationY:这三个属性控制View对象围绕支点进行2D和3D旋转。
  • scaleX和scaleY:这两个属性控制着View对象围绕它的支点进行2D缩放。
  • pivotX和pivotY:这两个属性控制着View对象的支点位置,围绕着这个支点进行旋转和缩放变换处理。默认情况下,该支点的位置就是View对象的中心点。
  • x 和 y:这是两个简单实用的属性,它描述了View对象在它容器中的最终位置,它是最初的左上角坐标和translationX、translationY值的累积和。
  • alpha:它表示View对象的alpha透明度。默认值是1(不透明),0代表完全透明(不可见)。

当一个属性没有get、set方法时,Google在应用层提供了两种方案来解决这个问题,一个是通过自定义一个属性类或者包装类,来间接地给这个属性增加get、set方法;或者通过ValueAnimator来实现, ValueAnimator在后面的内容中会说到。

先来看使用包装类的方法给一个属性增加get、set方法,代码如下所示:

private static class WrapperView{    private View mTarget;    public WrapperView(View target){        mTarget = target;    }    public int getWidth() {        return mTarget.getLayoutParams().width;    }    public void setWidth(int width) {        mTarget.getLayoutParams().width = width;        mTarget.requestLayout();    }}

通过以上代码,就给一个属性包装了一层,并给它提供了get、set方法。使用时只需要操纵包装类就可以间接调用到get、set方法了,代码如下所示:

        WrapperView wrapper = new WrapperView(view);        ObjectAnimator.ofInt(wrapper, "width", 50).setDuration(5000).start();

PropertyValuesHolder

类似视图动画中的AnimationSet,在属性动画中,如果针对同一个对象的多个属性,要同时作用多种动画,可以使用PropertyValuesHolder来实现。比如在平移的过程中,同时改变X、Y轴的缩放,可以这样实现,代码如下:

PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300f);PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2, pvh3).setDuration(1000).start();

ValueAnimator

ValueAnimator是属性动画的核心所在,ObjectAnimator也是继承自ValueAnimator。

ValueAnimator本身不提供任何动画效果,它更像是一个数值发生器,用来产生具有一定规律的数字,从而让调用者来控制动画的实现过程,ValueAnimator的一般使用方法如下所示,通常情况下,在ValueAnimator的AnimatorUpdateListener中监听数值的变换,从而完成动画变换。

ValueAnimator animator = ValueAnimator.ofFloat(0, 100);animator.setTarget(view);animator.setDuration(1000).start();animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {    @Override    public void onAnimationUpdate(ValueAnimator animation) {        Float value = (Float) animation.getAnimatedValue();        //TODO use the value    }});

动画事件的监听

一个完整的动画具有Start、Repeat、End、Cancel四个过程,通过Android提供的接口,可以方便地监听到这四个事件,代码如下所示:

ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", 0.5f);anim.addListener(new Animator.AnimatorListener() {    @Override    public void onAnimationStart(Animator animator) {    }    @Override    public void onAnimationEnd(Animator animator) {    }    @Override    public void onAnimationCancel(Animator animator) {    }    @Override    public void onAnimationRepeat(Animator animator) {    }});anim.start();

当然,大部分时候,我们都只是关心onAnimationEnd事件,所以android也提供了一个AnimatorListenerAdapter来让我们选择必要的事件进行监听,代码如下所示:

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

AnimatorSet

对一个属性同时作用多个属性效果,AnimatorSet与PropertyValuesHolder功能类似,但其可以实现更为精确的顺序控制,代码如下所示:

ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translateX", 300f);ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0 ,1f);ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0 ,1f);AnimatorSet set = new AnimatorSet();set.setDuration(1000);set.playTogether(animator1, animator2, animator3);set.start();

在属性动画中,AnimatorSet正是通过set.playTogether()、set.playSequentially()、set.play().with()、set.play().befor()、set.play().after()这些方法来控制多个动画的协同工作方式,从而做到对动画播放顺序的精确控制。

在XML中使用属性动画

属性动画同视图动画一样,也可以直接写在XML文件中,XML文件一般放在在animator目录中, 代码如下所示:

<?xml version="1.0" encoding="utf-8"?><objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="1000"    android:propertyName="scaleX"    android:valueFrom="1.0"    android:valueTo="2.0"    android:valueType="floatType"</objectAnimator>

在代码中使用XML定义的属性动画也非常简单,代码如下所示:

public void scaleX(View view) {    Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scalex);    anim.setTarget(view);    anim.start();    }

View的animate方法

在Android 3.0之后,Google给View增加了animate方法来直接驱动属性动画,代码如下所示,可以发现,其实animate方法可以认为是属性动画的一种简写方式。

view.animate()        .alpha(0)        .y(300)        .setDuration(300)        .withStartAction(new Runnable() {            @Override            public void run() {            }        })        .withEndAction(new Runnable() {            @Override            public void run() {                runOnUiThread(new Runnable() {                    @Override                    public void run() {                    }                });            }        })        .start();

代码下载

阅读全文
0 0
原创粉丝点击