注意:本篇文章是本人阅读关于Android动画的文章所写下的总结,方便以后查阅,所有内容非原创,侵权删。
本篇文章内容来自于
- Android高级进阶 顾浩鑫
- 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 代码实现
- 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"
/>
- 加载动画
ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator_object);
animator.setTarget(tvAnimPropertyObject);
animator.start();