Android Animation 系列——属性动画(Property Animation)

000 属性动画简介

属性动画是 Android API level 11(Android 3.0)中添加的动画框架,功能强大,扩展性强。介绍属性动画,就需要说明三个问题:

属性是什么?

用官方的话说,Property is a field in an object。更进一步解释,这里的属性是指一个对象中具有 setter/getter 方法的变量。

属性动画可以做什么?

一般来说,动画是一种视觉效果,但是属性动画的内容要更广泛,除了做一些视觉效果之外,属性动画还可以用类似动画的方式默默改变一些数据。当然,最主要的还是实现视觉效果,包括常见的透明度、缩放、平移、旋转效果,也可以扩展出其他的属性(比如颜色)。

与之前的 View Animation 有什么区别?

View Animation 是在 API level 1 开始支持的动画框架,内容只有基本的透明度、缩放、平移、旋转,且动画的对象只能是 View。

二者的区别有以下几点:

  1. 属性动画实际改变了动画目标的属性值,比如平移一个 View,View 的位置真实发生了改变,而 View Animation仅是改变了屏幕绘制位置,真实位置不变。
  2. 属性动画可以作用于没有绘制到屏幕上的对象。
  3. 属性动画可以作用于非 View 对象,也可以制作四类基本动画之外的动画效果。
  4. View Animation 的代码量更少,效率更高。

001 相关API说明

属性动画中新添加的类主要是这些:


property animation framework.jpg
Animator

作为属性动画的基类,Animator 提供了动画最基本的属性。

仅列出一部分(我觉得)常用的。

Method Name Function
start() 开始播放
cancel() 取消动画
isRunning() 是否正在播放
addListener 添加监听回调
setTarget 设置动画目标Object
setDuration 设置播放时长,单位:毫秒
setInterpolator 设置插值器

关于插值器的内容本文暂不介绍了。

ValueAnimator

构造方法

//直接创建
    ValueAnimator valueAnimator = new ValueAnimator();
//带参数创建
    ValueAnimator valueAnimator = ValueAnimator.ofFloat(1.0f, 2.0f);
    // ValueAnimator valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), Color.RED, Color.GREEN);
    // ...还有ofArgb,ofInt,ofPropertyValuesHolder

比起 Animator 增加的一些常用方法

Method Name Function
setStartDelay 设置动画启动延迟,单位:毫秒
addUpdateListener 添加Value更新的监听回调
setRepeatMode 设置重复播放模式,RESTART或REVERSE
setRepeatCount 设置重复播放次数
ObjectAnimtor

构造方法

//直接创建
    ObjectAnimator objectAnimator = new ObjectAnimator();
//带参数创建
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mView, "alpha", 1.0f, 0.7f);
    //...类似的构造方法有很多,就是参数不同,这些参数都可以通过setter方法设置。

ObjectAnimatior 增加了属性动画最基本的方法——设置属性。

Method Name Function
setProperty 设置动画目标属性
setPropertyName 通过name设置动画目标属性
setIntValues(int... values) 设置一系列动画参数,按顺序执行
setFloatValues(float... values) 设置一系列动画参数,按顺序执行
setObjectValues(Object... values) 设置一系列动画参数,按顺序执行
AnimatorSet

AnimatorSet 的功能就是把多个各种 Animator 对象整合成一个动画,有点类似与 ViewGroup。

Method Name Function
playTogether 多个动画一起播放
playSequentially 多个动画顺序播放

010 使用场景分析

Animator对象

ValueAnimator 的功能很单一,比较像“时间轴”,就是设置一个值,在一段时间内以某种规则变化。这也是
ObjectAnimator 实现动画的基础。

举个例子,通过 VlaueAnimator 改变 View 的颜色:

    private int mColor = Color.RED;
    public ValueAnimator valueAnimator;
//...
//...
    valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), mColor, Color.rgb(0,0,255));
    valueAnimator.setDuration(3000);
    valueAnimator.setInterpolator(new LinearInterpolator());
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mColor = (int) animation.getAnimatedValue();
            }
        });

onAnimationUpdate 方法中把变化后的颜色刷新到 UI 界面就行了。效果是这样的:

ValueAnimator sample.gif

相比之下 ObjectAnimator 才是属性动画中的主角,创建 ObjectAnimator 对象实现动画需要有几个要素:

  1. propertyName:要变化的属性名(String)
  2. target:具有该属性的 Object 对象
  3. values:对应属性的变化值,数据类型要和属性的类型一致

属性名接受一个 String 类型的参数,就很容易出错。可以通过输入 target 的 object 对象,在代码提示中找 setter 方法来确定属性名。View 的属性名是比较常用的,比如:alpharotationscaleXscaleYtranslationXtranslationYrotationXrotationY等。

举个例子,网络加载中可能会大量用到的一种loading动画。

    ObjectAnimator animator = new ObjectAnimator();
    animator.setPropertyName("rotation");
    animator.setTarget(ivLoading);
    animator.setFloatValues(0,360);
    animator.setDuration(900);
    animator.setRepeatMode(ObjectAnimator.RESTART);
    animator.setRepeatCount(ObjectAnimator.INFINITE);
    animator.setInterpolator(new LinearInterpolator());
    animator.start();

代码含义比较清晰,需要注意的是setInterpolator默认的插值器并不是线性的,下面给出两种效果,左侧是 LinearInterpolator ,右侧是默认的。

ObjectAnimatior Sample.gif
xml实现

xml 实现动画是一种比较合理的复用动画方式,可以有效避免在 Controller 层写过多只属于 View 层的代码。

属性动画的 xml 文件需要放在res/animator文件夹下。

语法与 View Animation 差别比较大,大概是这样子的:


xml animator(官方文档截图).png

直观感受就是比 View Animation 的 xml 实现麻烦很多,实际上由于 xml 文件的限制二者功能上差不多,应该是 View Animation 更加常用一点。(个人感受)

view.animate()

ObjectAnimator 的代码写起来不怎么好看,因为总是在 objectAnimator.xxx(),比起单独在Activity中实现某些交互效果,把简单而常用的动画效果封装成工具类会更理想一些。但是交互效果是千变万化的,总有一些独特的动画无法复用。

于是在 API level 12 中,出现了针对 View 的属性动画 ViewPropertyAnimtor。ViewProperty 中封装了 View 相关的常用动画参数的设置以及多种回调,并用 ObjectAnimator 实现了动画效果,对外提供了相当简单易懂的流式 API,使动画的代码也可以写的很爽。

使用方法:

  1. 获取 ViewPropertyAnimator 对象

ViewPropertyAnimator 没有 public 的构造方法,只能通过 View 对象的 animate() 方法获得。使用的 View 对象就是动画的 target。

ViewPropertyAnimator 对象是会重复使用的,多次调用'animate()'只会创建一个 ViewPropertyAnimator。

  1. 设置动画参数

相关的 API 名称都很明确,就不一一介绍效果了


ViewPropertyAnimator API.png
ViewPropertyAnimator API.png
  1. 设置回调(可选)

就是setListener方法。其实所有的动画都可以设置
Listener ,只是在 ViewPropertyAnimator 中更加重要,因为从 API 可以看出每一种动画只能传入一个参数,如果需要同一种动画多段执行,就只能通过监听动画结束修改参数值再开始动画。

setListener 方法接收一个 Animator.AnimatorListener 接口的实例,可以直接创建 Animator.AnimatorListener 实例实现所有方法,也可以创建 AnimatorListenerAdapter 只重写需要的方法。

ViewPropertyAnimator 的复用同样会影响 Listener,如果是同一个 View 的多个动画且不相关,需要在不需要 Listener 的动画中调用setListener(null)

这里也应该举个例子,不过没什么好的想法,姑且再写一遍
loading 动画,就当对比一下两种 API 格式吧。(kotlin代码,对比一下设置动画的 API 就好了)

ivLoadingRight.setOnClickListener {
    ivLoadingRight.animate()
            .rotationBy(360f)
            .setDuration(800)
              .setInterpolator(LinearInterpolator())
            .setListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator?) {
                    super.onAnimationEnd(animation)
                    ivLoadingRight.animate()
                            .rotationBy(360f)
                            .setDuration(800)
                              .setInterpolator(LinearInterpolator())
                            .start()
                }
            }).start()

011 结语

因为我并没有做过太多的动画效果,刚开始写的时候只想总结一下各种方法的用法和效果,然而那样就会不能避免的翻译官方文档,且内容杂乱,不易整理 demo。于是先写了一些简单的动画效果,依据实际代码反向整理了这篇文章。

文中 gif 图对应代码都在示例工程(AnimatorSample)中,地址:https://github.com/xhd-Git/Samples

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

推荐阅读更多精彩内容