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

属性动画框架Animator中使用最多的就是AnimatorSet和ObjectAnimator配合,使用ObjectAnimator进行更精细化控制,只控制一个对象的一个属性值,而使用多个ObjectAnimator组合到AnimatorSet形成一个动画。而且ObjectAnimator能够自动驱动,可以调用setFrameDelay(longframeDelay)设置动画帧之间的间隙时间,调整帧率,减少动画过程中频繁绘制界面,而在不影响动画效果的前提下减少CPU资源消耗。最重要的是,属性动画通过调用属性的get、set方法来真实地控制了一个View的属性值,因此强大的属性动画框架,基本可以实现所有的动画效果。

ObjectAnimator

ObjectAnimator简单使用的示例代码:

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

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

属性动画由于它真实地改变了一个View的属性,所以事件响应的区域也同样发生了改变。这点与视图动画框架不同,视图动画只是单纯地修改了显示。

在使用ObjectAnimator的时候,有一点非常重要,那就是要操纵的属性必须具有get、set方法(ObjectAnimator内部会通过Java反射机制来调用set、get方法修改对象属性值),不然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来实现。

使用包装类的方法给一个属性增加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);
        animator.start();
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                Float value = (Float) valueAnimator.getAnimatedValue();
                //use the value
            }
        });

动画事件的监听

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

        ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0.5f);
        animator.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) {

            }
        });
        animator.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文件中,在animator目录下新建scale.xml文件,代码如下所示:

<?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"/>

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

    public void scaleX(View view) {
        Animator animator = AnimatorInflater.loadAnimator(this, R.animator.scale);
        animator.setTarget(view);
        animator.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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值