Android学习笔记(九)| Android动画(下)—— 属性动画

参考书籍:《Android开发艺术探索》 任玉刚
如有错漏,请批评指出!

属性动画是API 11 新加入的特性,不同于View动画只能作用于View,它可以对任意对象做动画操作。比较常用的几个动画类有 ValueAnimator、ObjectAnimator、AnimatorSet,想要兼容API 11 以前的Android版本,我们可以使用开源动画库 nineoldandroids,这里就不去探讨它的使用方法了,下面我们来看属性动画的用法。

属性动画的用法

属性动画可以对任意对象的属性进行动画而不仅仅是View,动画默认时间是300ms,默认帧率是 10ms/帧。先来看看ValueAnimator 和 ObjectAnimator 这两个类:

ValueAnimator

ValueAnimator 这个类本身不作用于任何对象,它是在一定时间内对一个值进行平滑过渡,因此,我们要使用它来实现动画,就需要监听这个过渡过程,获取过渡值,利用这个过渡值来对实际的对象进行处理(可能不太好理解)。下面来看看代码:

ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 1000.0f);
animator.setDuration(100);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        Log.e("code", animation.getAnimatedValue()+"");
    }
});
animator.start();

先来看打印结果:

可以看到,这里实现的是在100ms内将一个数从1.0变为1000.0,每一帧(即每更新一次数值)会回调一次 onAnimationUpdate() 方法,在这个方法中,我们可以通过传入的 ValueAnimation 对象的 getAnimatedValue() 方法获取这个值,利用这个值来实现动画效果。

当然,还有更简单的方法,我们重点来看 ObjectAnimator 类。

ObjectAnimator

ObjectAnimator 类 是继承自 ValueAnimator 类的,它主要重写了 ValueAnimator 的几个 ofXXX() 方法,让动画与对象直接相关联,这样我们就不需要自己来监听动画过程,控制动画效果了。下面来看几个示例:
注:下面的代码中涉及到一些基本属性,在 Android学习笔记(七)| Android动画(上)—— View动画 中已经讲过,没看过的话,建议移步。

  • 实现平移、旋转、缩放、透明度动画
        // translationX —— 在 X 轴方向平移 translationY —— 在 Y 轴方向平移
        ObjectAnimator translateAnimator = ObjectAnimator.ofFloat(tvObjAnim, "translationX", 0.0f, 200.0f);
        translateAnimator.setDuration(1000);
        translateAnimator.setRepeatMode(ValueAnimator.REVERSE);
        translateAnimator.setRepeatCount(ValueAnimator.INFINITE);
        translateAnimator.start();
    
        // rotationX —— 以水平中心线为轴旋转  rotationY —— 以竖直中心线为轴旋转
        ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(tvRotate, "rotationX", 0, 180);
        rotateAnimator.setDuration(1000);
        rotateAnimator.setRepeatMode(ValueAnimator.REVERSE);
        rotateAnimator.setRepeatCount(ValueAnimator.INFINITE);
        rotateAnimator.start();
    
        // scaleX —— 以中心为缩放轴点横向缩放 scaleY —— 以中心为缩放轴点竖直缩放
        ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(tvScale, "scaleX", 1.0f, 2.0f);
        scaleAnimator.setDuration(1000);
        scaleAnimator.setRepeatMode(ValueAnimator.REVERSE);
        scaleAnimator.setRepeatCount(ValueAnimator.INFINITE);
        scaleAnimator.start();
    
        // alpha —— 改变透明度
        ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(tvAlpha, "alpha", 1, 0);
        alphaAnimator.setDuration(1000);
        alphaAnimator.setRepeatMode(ValueAnimator.REVERSE);
        alphaAnimator.setRepeatCount(ValueAnimator.INFINITE);
        alphaAnimator.start();
    
  • 实现颜色渐变
        ObjectAnimator animator = ObjectAnimator.ofInt(tvColor, "backgroundColor", 0xff689f38, 0xff34a2da);
        animator.setDuration(3000);
        // 设置针对Color属性的估值器
        animator.setEvaluator(new ArgbEvaluator());
        animator.setRepeatMode(ValueAnimator.REVERSE);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.start();
    
    这里涉及到一个插值器的概念,后面会讲到。这段代码实现的效果就是在3s内将View的颜色从 #689f38 渐变为 #34a2da , 并且重复模式是逆转,无限循环。
AnimatorSet

AnimatorSet 是动画集合,也就是同时播放一组动画。

    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.playTogether(
        ObjectAnimator.ofFloat(tvObjAnim, "translationX", 0.0f, 200.0f), 
        ObjectAnimator.ofFloat(tvRotate, "rotationX", 0, 180),
        ObjectAnimator.ofFloat(tvScale, "scaleX", 1.0f, 2.0f),
        ObjectAnimator.ofFloat(tvAlpha, "alpha", 1, 0)
    );
    animatorSet.setDuration(1000);
    animatorSet.start();

想要让动画循环播放的话,还是需要给每个ObjectAnimator单独指定相关属性。

上面这些效果都可以通过 xml 来定义,在前面的文章也讲过xml定义,只是标签不同,这里就不赘述了。

  • <animator/> 标签 对应 ValueAnimator 类
  • <objectAnimator/> 标签 对应 ObjectAnimator 类
    propertyName:表示作用对象的属性的名称(translationX、rotationX等)
    valueType属性有两个可选值:intType——整型,floatType——浮点型。
    注意:当 propertyName 指定为颜色相关属性时,不需要指定 valueType 属性,系统会自动对颜色类型的属性做处理。
  • <set/> 标签 对应 AnimatorSet 类
    ordering 属性有两个可选值:together——子动画同时播放,sequentially——子动画按顺序依次播放。

插值器 和 估值器 的概念

  • TimeInterpolator 翻译为时间插值器,它的作用是根据当前时间流逝的百分比来计算当前属性值改变的百分比,系统预置了 LinearInterpolator(线性插值器:匀速动画)、AccelerateDecelerateInterpolator(加速减速插值器:动画两头慢中间快) 和 DecelerateInterpolator(减速插值器:动画越来越慢)等。
  • TypeEvaluator 翻译为估值器,它的作用是根据 TimeInterpolator 计算出的属性改变百分比来计算当前时间节点的属性值,系统预置有 IntEvaluator(针对整型属性)、FloatEvaluator(针对浮点型属性)和ArgbEvaluator(针对 Color 属性)。

属性动画的监听器

属性动画提供了监听器用于监听动画的播放过程,主要有两个接口:AnimatorUpdateListener 和 AnimatorListener。

  • AnimatorListener
    接口定义如下:
    public static interface AnimatorListener {
        default void onAnimationStart(Animator animation, boolean isReverse) {
            onAnimationStart(animation);
        }

        default void onAnimationEnd(Animator animation, boolean isReverse) {
            onAnimationEnd(animation);
        }

        void onAnimationStart(Animator animation);

        void onAnimationEnd(Animator animation);

        void onAnimationCancel(Animator animation);

        void onAnimationRepeat(Animator animation);
    }

可以看到,AnimatorListener 可以监听动画的开始、结束、取消以及重复播放。

  • AnimatorUpdateListener
    接口定义:
    public static interface AnimatorUpdateListener {
        /**
         * <p>Notifies the occurrence of another frame of the animation.</p>
         *
         * @param animation The animation which was repeated.
         */
        void onAnimationUpdate(ValueAnimator animation);
    }

这个接口会监听动画的整个过程,前面说过动画是由许多帧组成的,也就是说,每播放一帧,onAnimationUpdate() 方法就会被调用一次。


上一篇:Android学习笔记(八)| Android动画(中)—— 帧动画
下一篇:Android学习笔记(十)| Drawable的基本用法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容