Android动画机制总结笔记--属性动画PropertyAnimation篇之ObjectAnimator

注意:本篇文章是本人阅读关于Android动画的文章所写下的总结,方便以后查阅,所有内容非原创,侵权删。

本篇文章内容来自于

  1. Android高级进阶 顾浩鑫
  2. Android自定义控件三部曲文章索引之动画篇

目录

4.属性动画PropertyAnimation(基类Animator)
--4.2 ObjectAnimator(ValueAnimator的子类 实际开发中最常用)
----4.2.1 ObjectAnimator构造方法(5种)
----4.2.2 ObjectAnimator代码实现
------4.2.2.1 ofInt ofFloat ofObject构造
------4.2.2.2 ofPropertyValuesHolder构造
----4.2.3 ObjectAnimator动画原理
----4.2.4 ObjectAnimator XML实现

4.属性动画PropertyAnimation(基类Animator)

一个完整的属性动画由两部分组成:
1.计算动画各个帧的相关属性值
2.将这些属性值设置给指定的对象

4.2 ObjectAnimator(ValueAnimator的子类 实际开发中最常用)

是ValueAnimator的子类,封装实现了第二部分功能。
实际开发用到的更多的是ObjectAnimator,只有在ObjectAnimator实现不了的情景下,才考虑使用ValueAnimator

4.2.1 ObjectAnimator构造方法

由于ObjectAnimator是派生自ValueAnimator的,所以ValueAnimator中所能使用的方法,在ObjectAnimator中都可以正常使用。
但ObjectAnimator也重写了几个方法,比如ofInt(),ofFloat()等。

public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
public static ObjectAnimator ofArgb(Object target, String propertyName, int... values) 
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) 
public static ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values) 
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values) 

4.2.2 ObjectAnimator代码实现

4.2.2.1 ofInt ofFloat ofObject
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "rotation", 0,180,0);
objectAnimator.setDuration(3000);
objectAnimator.start();

ObjectAnimator做动画,并不是根据控件xml中的属性来改变的,而是通过指定属性所对应的set方法来改变的。

比如,我们上面指定的改变rotation的属性值,ObjectAnimator在做动画时就会到指定控件(TextView)中去找对应的setRotation()方法来改变控件中对应的值。

在View中有关动画,总共有下面几组set方法:

//1、透明度:alpha
public void setAlpha(float alpha)
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "alpha", 1, 0, 1);

//2、旋转度数:rotation、rotationX、rotationY
public void setRotation(float rotation) 表示旋转度数
public void setRotationX(float rotationX) 表示旋转度数
public void setRotationY(float rotationY) 表示旋转度数
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "rotation", 0,180,0);

//3、平移:translationX、translationY
public void setTranslationX(float translationX) 向右为正方向
public void setTranslationY(float translationY) 向下为正方向
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "translationX", 0, 200, -200,0);

//缩放:scaleX、scaleY
public void setScaleX(float scaleX) scaleX表示缩放倍数
public void setScaleY(float scaleY) scaleY表示缩放倍数
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "scaleX", 0, 3, 1);

使用时要注意


关于属性的get方法
当且仅当我们在创建ObjectAnimator时,只给他传递了一个过渡值的时候,系统才会调用属性对应的get函数来得到动画的初始值!

4.2.2.2 ofPropertyValuesHolder

构造方法如下

public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)  
4.2.2.2.1.什么是PropertyValuesHolder

PropertyValuesHolder这个类的意义就是,它其中保存了动画过程中所需要操作的属性和对应的值。
我们通过ofFloat(Object target, String propertyName, float… values)构造的动画,ofFloat()的内部实现其实就是将传进来的参数封装成PropertyValuesHolder实例来保存动画状态。在封装成PropertyValuesHolder实例以后,后期的各种操作也是以PropertyValuesHolder为主的。
ObjectAnimator给我们提供了一个口子,让我们自己构造PropertyValuesHolder来构造动画。

4.2.2.2.2 PropertyValuesHolder构造函数
public static PropertyValuesHolder ofFloat(String propertyName, float... values)  
public static PropertyValuesHolder ofInt(String propertyName, int... values)   
public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object... values)  
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values) 
4.2.2.2.2 PropertyValuesHolder常用方法
//设置动画的Evaluator 
public void setEvaluator(TypeEvaluator evaluator)  
//用于设置ofFloat所对应的动画值列表 
public void setFloatValues(float... values)  
//用于设置ofInt所对应的动画值列表 
public void setIntValues(int... values)  
//用于设置ofKeyframe所对应的动画值列表 
public void setKeyframes(Keyframe... values)  
//用于设置ofObject所对应的动画值列表 
public void setObjectValues(Object... values)  
//设置动画属性名 
public void setPropertyName(String propertyName) 

setFloatValues(float… values)对应PropertyValuesHolder.ofFloat(),用于动态设置动画中的数值。setIntValues、setKeyframes、setObjectValues同理;
setPropertyName用于设置PropertyValuesHolder所需要操作的动画属性名;

4.2.2.2.3 使用PropertyValuesHolder创建ObjectAnimator

1⃣️ofFloat ofInt

PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat("rotation", 60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);
PropertyValuesHolder backgroundColor = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(tvAnimPropertyObject, rotation, backgroundColor);
objectAnimator.setDuration(3000);
objectAnimator.setInterpolator(new AccelerateInterpolator());
objectAnimator.start();

2⃣️ofObject

PropertyValuesHolder charText = PropertyValuesHolder.ofObject("CharText", new CharEvaluator(), new Character('A'), new Character('Z'));
ObjectAnimator objectAnimator1 = ObjectAnimator.ofPropertyValuesHolder(mtvAnimPropertyObject, charText);
objectAnimator1.setDuration(3000);
objectAnimator1.start();

3⃣️ofKeyFrame
① 什么是keyFrame
如果要控制动画速率的变化,我们可以通过自定义插值器,也可以通过自定义Evaluator来实现。但有一定的难度。为了解决方便的控制动画速率的问题,谷歌定义了一个KeyFrame的类,也就是关键帧。

就是类似动画中的关键帧:
比如我们要让一个球在30秒时间内,从(0,0)点运动到(300,200)点,我们只需要定义两个关键帧,在动画开始时定义一个,把球的位置放在(0,0)点;在30秒后,再定义一个关键帧,把球的位置放在(300,200)点。在动画 开始时,球初始在是(0,0)点,30秒时间内就adobe flash就会自动填充,把球平滑移动到第二个关键帧的位置(300,200)点;

一个关键帧必须包含两个原素,第一时间点,第二位置。即这个关键帧是表示的是某个物体在哪个时间点应该在哪个位置上。

② KeyFrame 构造方法

// ofFloat 
public static Keyframe ofFloat(float fraction)   
public static Keyframe ofFloat(float fraction, float value)  
//ofInt 
public static Keyframe ofInt(float fraction)  
public static Keyframe ofInt(float fraction, int value) 
//ofObject
public static Keyframe ofObject(float fraction, Object value)
public static Keyframe ofObject(float fraction)

public static Keyframe ofFloat(float fraction, float value)

  • fraction:表示当前的显示进度,即从加速器中getInterpolation()函数的返回值;
  • value:表示当前应该在的位置

Keyframe kf0 = Keyframe.ofFloat(0, 0);
Keyframe kf1 = Keyframe.ofFloat(0.1f, -20f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0);
比如Keyframe.ofFloat(0, 0)表示动画进度为0时,动画所在的数值位置为0;Keyframe.ofFloat(0.25f, -20f)表示动画进度为25%时,动画所在的数值位置为-20;Keyframe.ofFloat(1f,0)表示动画结束时,动画所在的数值位置为0;

public static Keyframe ofFloat(float fraction)

  • 参数fraction,表示当前关键帧所在的动画进度位置。

那在这个进度时所对应的值 用setValue来设置

③KeyFrame常用方法

//设置fraction参数,即Keyframe所对应的进度 
public void setFraction(float fraction)   
//设置当前Keyframe所对应的值 
public void setValue(Object value)  
//设置Keyframe动作期间所对应的插值器 
public void setInterpolator(TimeInterpolator interpolator)  

③ 代码实现
1.使用ofFloat/ofInt构造KeyFrame

Keyframe frame0 = Keyframe.ofFloat(0f, 0);
Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
Keyframe frame2 = Keyframe.ofFloat(1, 0);
PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofKeyframe("rotation", frame0, frame1, frame2);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofPropertyValuesHolder(tvAnimPropertyObject, propertyValuesHolder);
objectAnimator2.setDuration(3000);
objectAnimator2.start();

2.使用ofObject构造KeyFrame

Keyframe frame_0 = Keyframe.ofObject(0f, new Character('A'));
Keyframe frame_1 = Keyframe.ofObject(0.1f, new Character('L'));
Keyframe frame_2 = Keyframe.ofObject(1, new Character('Z'));
PropertyValuesHolder propertyValuesHolder1 = PropertyValuesHolder.ofKeyframe("CharText", frame_0, frame_1, frame_2);
propertyValuesHolder1.setEvaluator(new CharEvaluator());
ObjectAnimator objectAnimator3 = ObjectAnimator.ofPropertyValuesHolder(mtvAnimPropertyObject, propertyValuesHolder1);
objectAnimator3.setDuration(3000);
objectAnimator3.start();

④ 关于KeyFrame的插值器的注意点
关键帧可通过以下方法设置插值器

//设置Keyframe动作期间所对应的插值器 
public void setInterpolator(TimeInterpolator interpolator)  

如果给这个Keyframe设置上插值器,
那么这个插值器就是从上一个Keyframe开始到当前设置插值器的Keyframe时,这个过程值的计算是利用这个插值器的

Keyframe frame0 = Keyframe.ofFloat(0f, 0);  
Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);  
frame1.setInterpolator(new BounceInterpolator());

在frame0到frame1的中间值计算过程中,就是用的就是回弹插值。
给Keyframe.ofFloat(0f, 0)设置插值器是无效的,因为它是第一帧。

⑤ 关于关键帧KeyFrame的注意点
如果去掉第0帧(fraction为0),将以第一个关键帧为起始位置
如果去掉结束帧(fraction为1),将以最后一个关键帧为结束位置
使用Keyframe来构建动画,至少要有两个或两个以上帧,否则会崩

4.2.3 ObjectAnimator动画原理


1⃣️首先通过加速器产生当前进度的百分比,
然后再经过Evaluator生成对应百分比所对应的数字值。
这两步与ValueAnimator是完全一样的,

2⃣️唯一不同的是最后一步
在ValueAnimator中,我们要通过添加监听器来监听当前数字值。
而在ObjectAnimator中,则是先根据属性值拼装成对应的set函数的名字,比如这里的scaleY的拼装方法就是将属性的第一个字母强制大写后,与set拼接,所以就是setScaleY。然后通过反射找到对应控件的setScaleY(float scaleY)函数,将当前数字值做为setScaleY(float scale)的参数将其传入。

3⃣️调用完set方法,set方法内部会对控件进行设置,动画在进行时每隔十几毫秒会刷新一次,set函数也会每隔十几毫秒会被调用一次(将动画中间值传给他)。

4.2.4 ObjectAnimator XML实现

标签<objectAnimator />对应ObjectAnimator

4.2.4.1 <objectAnimator />标签字段意义及使用方法

<objectAnimator
    android:propertyName="string"
    android:duration="int"
    android:valueFrom="float | int | color"
    android:valueTo="float | int | color"
    android:startOffset="int"
    android:repeatCount="int"
    android:repeatMode=["repeat" | "reverse"]
    android:valueType=["intType" | "floatType"]
    android:interpolator=["@android:interpolator/XXX"]/>

android:propertyName:对应属性名,即ObjectAnimator所需要操作的属性名。
android:valueType:表示参数值类型,取值为intType和floatType;与android:valueFrom、android:valueTo相对应。

4.2.4.2 代码实现

  1. res/animator新建animtor_object.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="TranslationY"
    android:duration="2000"
    android:valueFrom="0.0"
    android:valueTo="400.0"
    android:valueType="floatType"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:repeatCount="1"
    android:repeatMode="reverse"
    android:startOffset="2000"
    />
  1. 加载动画
ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator_object);
animator.setTarget(tvAnimPropertyObject);
animator.start();

更多案例

ObjectAnimator运用在自定义控件(弹性圆)上

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