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

原创 2016年06月02日 11:32:06

属性动画框架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();
版权声明:本文为博主原创文章,未经博主允许不得转载。

Android源码分析—属性动画的工作原理

转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/17853275 前言 本文为Android动画系列的最后一篇文章,通过对源码的...
  • singwhatiwanna
  • singwhatiwanna
  • 2014年01月05日 00:05
  • 20464

Android 属性动画探究(二)——TypeEvaluator解析与自定义

TypeEvaluator是直接改变动画的属性值的,比如要改变颜色属性,可以直接改变其值为"#FFFFFF",而Interpolator改变的是进度,如可以直接指定瞬间完成动画整体的80%。但是两者不...
  • L_wwbs
  • L_wwbs
  • 2016年11月29日 09:17
  • 399

Android之属性动画、值动画

Android属性动画 什么是Android属性动画 同类技术对比 补间动画Tween Animation 帧动画Frame Animation 属性动画Property Animation 属性动画...
  • biezhihua
  • biezhihua
  • 2015年05月09日 11:18
  • 4396

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

在Android3.0之后,google就提出了属性动画,帮助开发者实现更丰富的动画效果ObjectAnimatorObjectAnimator是属性动画中最重要的实现类, 创建一个ObjectAni...
  • lj402159806
  • lj402159806
  • 2017年08月06日 22:39
  • 159

Android属性动画用法(中)

昨天,我们通过Java代码的形式实现了一些简单的属性动画效果,今天,让我们通过xml文件来实现一下同样的效果吧。虽然xml写起来比较麻烦,不像昨天代码中编写的只需要几行代码就搞定,但是xml形式好在易...
  • s1674521
  • s1674521
  • 2017年04月17日 17:43
  • 267

动画(五)属性动画的实现原理

原文地址:点击打开链接 1.ValueAnimator ValueAnimator可以说是整个属性动画框架的核心类,动画的驱动就是在此类中实现的。下面举一个ValueAnimator的...
  • weishiwei0923
  • weishiwei0923
  • 2015年10月29日 13:56
  • 623

Android属性动画深入分析:让你成为动画牛人

转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/17841165 前言 感谢你阅读本文,我坚信读完本文肯定不会让你失望的。想要做...
  • singwhatiwanna
  • singwhatiwanna
  • 2014年01月04日 18:29
  • 41258

Android属性动画优化(更高效的使用属性动画)

Android属性动画优化
  • rentee
  • rentee
  • 2016年08月19日 16:03
  • 9371

Android属性动画封装之快速构建动画

Android实现动画效果的方式主要有帧动画、补间动画、属性动画。关于安桌动画的基础知识可以查看这篇文章 Android属性动画完全解析 这里我要讲的是如何快速构建出一个动画效果,如下图: 如果我...
  • u012964944
  • u012964944
  • 2016年03月11日 15:04
  • 1211

Android开发——View动画、帧动画和属性动画详解

0. 前言  Android动画是面试的时候经常被问到的话题。我们都知道Android动画分为三类:View动画、帧动画和属性动画。先对这三种动画做一个概述。View动画是一种渐进式动画,通过图像的平...
  • SEU_Calvin
  • SEU_Calvin
  • 2016年10月02日 19:28
  • 32717
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android动画机制与使用技巧(二)——属性动画分析
举报原因:
原因补充:

(最多只允许输入30个字)