分类
Android 官方提供了两种动画:
- 属性动画(Property Animation)通过改变对象的属性实现动画效果;
- 视图动画(View Animation)作用于 View 的动画,视图动画又可以分为两类:
- 帧动画(Frame Animation)通过一组图片有序播放实现动画视觉效果;
- 补间动画(Tween Animation)通过对视图进行一系列的动作变化实现动画效果;
一、帧动画
帧动画其实是 Drawable,用作 View 的背景,在 res/drawable 目录下通过 <animation-list> 标签定义
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot=""
android:variablePadding=""
android:visible="">
<item android:drawable="" android:duration=""/>
</animation-list>
对应的 Drawable 的子类是 AnimationDrawable 类,构造方法:
public AnimationDrawable()
添加一帧动画:
public void addFrame(@NonNull Drawable frame, int duration)
获取到 AnimationDrawable 对象之后调用 start()
方法开始动画
二、补间动画
Animation 类位于 android.view.animation 包下,直接子类有五个。
1、Animation
a.xml 属性
上面列出了 Animation 类的所有 xml 属性以及相关的方法。
- android:duration:动画的执行时间,单位毫秒;
- android:fillBefore:动画结束时画面停留在此动画的第一帧; 默认值为 true;
- android:fillAfter:动画结束是画面停留在此动画的最后一帧。默认值为false;
- android:repeatCount:动画重复执行的次数;
- android:repeatMode:动画重复执行模式,有 restart 和 reverse 两种;
- android:startOffset:动画开始的延迟时间;
- android:detachWallpaper:是否在壁纸上运行;
- android:zAdjustment:被设置动画的内容运行时在Z轴上的位置(top/bottom/normal),默认为 normal;
- android:interpolator:插值器;
b.监听器
Animation 类内部定义监听器 AnimationListener,定义了在动画开始、结束、重复时的回调方法,通过
setAnimationListener
方法设置。
c.一些 public 方法
除了设置 xml 属性的 setter 方法之外,还有一些常用的 public 方法:
public void start()
public void startNow()
public void setStartTime(long startTimeMillis)
public void reset()
public void cancel()
//设置动画背景颜色,如果为 0,则没有背景
public void setBackgroundColor(@ColorInt int bg)
d.定义
动画有两种定义方式,一种是在 res/anim 目录中定义,通过 AnimationUtils#loadAnimation()
方法加载另一种是直接在代码中通过构造方法创建对象。
视图动画只能给 View 使用,所以是通过 View 的方法开始动画和清除动画的
public void startAnimation(Animation animation)
public void clearAnimation()
2、TranslateAnimation(平移动画)
a.xml 文件定义
在 res/anim 目录中定义:
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta=""
android:fromYDelta=""
android:toXDelta=""
android:toYDelta=""
>
</translate>
使用 translate
标签,动画的起始点和结束点是 View 的左上角坐标,通过偏移量的方式来定义:
- android:fromXDelta="",android:fromYDelta="":起始点 x,y 坐标,可以为** 数值、百分数、百分数p,数值表示当前 View 的左上角加上 数值px 作为起始点,即以 View 左上角为原点的坐标,百分数表示当前 View 的左上角加上 View宽高 * 百分数 作为起始点,百分数p表示当前 View 的左上角加上 父控件宽高 * 百分数 **作为起始点;
- android:toXDelta="", android:toYDelta="":结束点 x,y 坐标,取值同上;
b.代码定义
public 的构造方法:
public TranslateAnimation (Context context, AttributeSet attrs)
public TranslateAnimation (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
public TranslateAnimation (int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)
第三个构造方法不仅规定了起始点和结束点 x,y 坐标,还规定了每一个偏移值的类型,类型是在 Animation 类中以静态常量的方式来定义的:
有三种值 ABSOLUTE(绝对)、RELATIVE_TO_SELF(相对自身)、RELATIVE_TO_PARENT(相对父控件)
默认值为 ABSOLUTE,所以第二个构造方法中的参数为绝对数值
2、ScaleAnimation
a.xml 文件定义
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX=""
android:pivotY=""
android:fromXScale=""
android:fromYScale=""
android:toXScale=""
android:toYScale=""
>
</scale>
scale
标签定义,缩放中心点默认为 View 左上角,通过偏移量来定义:
- android:pivotX="",android:pivotY="":缩放中心点 x,y 坐标,可以为** 数值、百分数、百分数p,数值表示当前 View 的左上角加上 数值px 作为中心点,百分数表示当前 View 的左上角加上 View宽高 * 百分数 作为中心点,百分数p表示当前 View 的左上角加上 父控件宽高 * 百分数 **作为中心点;
- android:fromXScale="",android:fromYScale="",android:toXScale="",android:toYScale="":开始时和结束时 x 方向和 y 方向缩放比例,1.0表示无变化;
b.代码定义
public ScaleAnimation (Context context, AttributeSet attrs)
public ScaleAnimation (float fromX, float toX, float fromY, float toY)
public ScaleAnimation (float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)
public ScaleAnimation (float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
第二个构造方法只确定了缩放比例,缩放中心点默认为 View 左上角;
第三个构造方法除了定义了缩放比例,还定义了绝对数值类型的所方中心点偏移量;
第四个构造方法规定了缩放中心点偏移量的类型;
3、RotateAnimation
a.xml 文件定义
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX=""
android:pivotY=""
android:fromDegrees=""
android:toDegrees=""
android:drawable=""
android:visible=""
>
</rotate>
使用 rotate
标签,需要声明的属性为旋转的中心点和旋转角度:
- android:pivotX="",android:pivotY="":旋转中心点坐标相对 View 左上角坐标偏移量,取值和默认值和 TranslateAnimation 平移坐标以及 ScaleAnimation 缩放中心点坐标相同;
- android:fromDegrees="",android:toDegrees="":旋转起始角度和结束角度,正值为顺时针度数,负值为逆时针度数;
b.代码定义
构造方法:
public RotateAnimation (Context context, AttributeSet attrs)
public RotateAnimation (float fromDegrees, float toDegrees)
public RotateAnimation (float fromDegrees, float toDegrees, float pivotX, float pivotY)
public RotateAnimation (float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
第二个构造方法只确定了旋转角度,旋转中心点默认为 View 左上角,第二个构造方法旋转中心点偏移量为绝对数值,第三个构造方法规定了旋转中心点偏移量的类型;
4.AlphaAnimaion
a.xml 文件定义
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha=""
android:toAlpha=""
>
</alpha>
只需要声明起始和结束的透明度值,取值为 0.0~1.0,0.0表示全透明,1.0表示完全不透明
b.代码定义
构造方法:
public AlphaAniamtion(Context context,AttributeSet attrs)
public AlphaAnimation (float fromAlpha, float toAlpha)
5.AnimationSet
a.xml 文件定义
<set xmlns:android="http://schemas.android.com/apk/res/android"
>
...
...
</set>
通过 set
标签定义,和其它四个 Animation 类的使用方法相同
b.代码定义
构造方法:
public AnimationSet(Context context, AttributeSet attrs)
public AnimationSet(boolean shareInterpolator)
通过 addAnimation
方法来添加一个动画
public void addAnimation (Animation a)
6.Interpolate
见下文。
三、属性动画
Animator 类位于 android.animation 包下,有两个直接子类 AnimatorSet 和 ValueAnimator,两个间接子类 ObjectAnimator 和 TimeAnimator
1、视图动画和属性动画的区别
- 视图动画作用对象只限制为 View,而属性动画作用对象不限为
View,可以是任何对象。 - 视图动画只能改变 View 的位置或者视觉效果,并不能改变其属性。
2、Animator
Animator 是一个抽象类,为子类定义了一些方法和接口
public 方法
public void start()
public void cancel()
public void end()
public void pause()
public void resume()
public abstract void setStartDelay(long startDelay);
public abstract Animator setDuration(long duration);
public abstract void setInterpolator(TimeInterpolator value);
public void addListener(AnimatorListener listener)
public void removeListener(AnimatorListener listener)
public void addPauseListener(AnimatorPauseListener listener)
public void removePauseListener(AnimatorPauseListener listener)
public void removeAllListeners()
监听器
3、ValueAnimator
Animator 同样有两种定义方式,一种是通过 xml 文件定义,然后通过 AnimatorInflater#loadAnimator()
方法加载动画,和补间动画不同的是在 res/animator 目录下面,另一种是在代码中使用相应的方法定义。
xml 文件定义
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration=""
android:interpolator=""
android:repeatCount=""
android:repeatMode=""
android:startOffset=""
android:valueFrom=""
android:valueTo=""
android:valueType="">
</animator>
<animator>
标签定义的是 ValueAnimator 对象,上面列出了定义动画时使用到的属性,其中 android:valueType
属性声明了值的类型,有 intType、floatType、colorType、pathType 四种类型。
还可以使用 propertyValuesHolder
和 keyframe
标签定义 ValueAnimator
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:repeatCount="1"
android:repeatMode="reverse">
<propertyValuesHolder>
<keyframe android:fraction="0" android:value="1"/>
<keyframe android:fraction=".2" android:value=".4"/>
<keyframe android:fraction="1" android:value="0"/>
</propertyValuesHolder>
</animator>
Keyframe
Keyframe 保存有值动画的一个时间、值对,ValueAnimator 的值从一个 Keyframe 变化到另一个 Keyframe,每一个 Keyframe 也有一个 TimeInterpolate 对象。
Keyframe 有三个成员变量:
//时间
float mFraction;
public float getFraction()
public void setFraction(float fraction)
//值类型
Class mValueType;
public Class getType()
//插值器
private TimeInterpolator mInterpolator = null;
public TimeInterpolator getInterpolator()
public void setInterpolator(TimeInterpolator interpolator)
Keyframe 是一个抽象类,相关的方法返回的是对应的子类对象。
public static Keyframe ofInt(float fraction, int value)
public static Keyframe ofInt(float fraction)
public static Keyframe ofFloat(float fraction, float value)
public static Keyframe ofFloat(float fraction)
public static Keyframe ofObject(float fraction, Object value)
public static Keyframe ofObject(float fraction)
Keyframe 内部定义了三个子类:ObjectKeyframe、IntKeyframe、FloatKeyframe。
看一下 ObjectKeyframe 类的实现:
子类内部又定义了一个成员变量 mValue,在 ObjectKeyframe 中是 Object 类型的,并且重写了 Keyframe 类的 getValue 和 setValue 方法,在
Keyframe#ofObject
方法就是通过 Objectkeyframe 的构造方法创建了一个对象,在构造函数内部给成员变量 mFraction 和 mValue 赋值,这里的 Object 参数可以为任何类的对象,当 value 为 null 时,默认为 Object 类型。
PropertyValueHolder
PropertyValuesHolder 可以暂存动画的属性和值使一个动画可以同时操作多个属性,有时可以替代 AnimatorSet。
PropertyValuesHolder 类的几个重要成员变量:
//属性名称
String mPropertyName;
public void setPropertyName(String propertyName)
//值类型
Class mValueType;
//属性值通过一组 Keyframes 来存储
Keyframes mKeyframes = null;
public void setKeyframes(Keyframe... values)
//以下三个方法内部通过 Keyframe#ofXXX 方法创建 Keyframe 对象并赋值给成员变量 mKeyframes
public void setIntValues(int... values)
public void setFloatValues(float... values)
public void setObjectValues(Object... values)
PropertyValuesHolder 的两个构造方法都是 private 的
private PropertyValuesHolder(String propertyName)
private PropertyValuesHolder(Property property)
所以要通过内部的一系列 ofXXX 方法创建 PropertyValuesHolder 对象:
public static PropertyValuesHolder ofInt(String propertyName, int... values)
public static PropertyValuesHolder ofInt(Property<?, Integer> property, int... values)
public static PropertyValuesHolder ofFloat(String propertyName, float... values)
public static PropertyValuesHolder ofFloat(Property<?, Float> property, float... values)
public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object... values)
public static PropertyValuesHolder ofObject(String propertyName,TypeConverter<PointF, ?> converter, Path path)
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)
public static PropertyValuesHolder ofKeyframe(Property property, Keyframe... values)
ofXXX 方法创建相应的 PropertyValuesHolder 对象,并通过 PropertyValuesHolder 类的 setXXX 给 mKeyframes 赋值。
public 方法
public void start()
public void cancel()
public void end()
public void resume()
public void pause()
public void reverse()
public Object getAnimatedValue()
public Object getAnimatedValue(String propertyName)
public float getAnimatedFraction()
代码创建对象
一般不使用 ValueAnimator 的构造方法而是通过 ofXXX 方法:
public static ValueAnimator ofInt(int... values)
public static ValueAnimator ofFloat(float... values)
public static ValueAnimator ofArgb(int... values)
public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values)
ofXXX 方法内部的操作都是创建一个 ValueAnimtor 对象,然后通过 ValueAnimator#setXXXValues 方法把 values 封装成 PropertyValuesHolder 数组
ValueAnimator 的值是存放在 PropertyValuesHolder 类型的数组成员变量 mValues 中的,数组中的每一个元素表示一个属性,可以看到在 setIntValues 方法中,当 mValues 不为 null 时,把数组中的第一个 PropertyValuesHolder 元素取出来,然后调用 PropertyValuesHolder#setIntValues 方法,把值设置给该 PropertyValuesHolder 对象,前面已经说过 setXXXValues 方法内部调用 Keyframe#ofXXX 方法,当 mValues 为 null 时,最终是通过 PropertyValuesHolder#ofInt 方法生成 PropertyValuesHolder 对象然后调用了 setValues 方法
setValues 则是生成一个 PropertyValuesHolder 数组,在 ProertyValuesHolder#ofObject 方法中调用了该方法,所以 ValueAnimator 可以通过 ofPropertyValuesHolder 对多个属性动画。
监听
public void addUpdateListener(AnimatorUpdateListener listener)
public void removeAllUpdateListeners()
public void removeUpdateListener(AnimatorUpdateListener listener)
ValueAnimator 内部定义了接口监听动画的更新,通过在回调方法中调用参数的 ValueAnimator#getAnimatedValue 方法获取到值动画的当前进度所对应的值。
4、ObjectAnimator
xml 文件中定义
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueTo="200"
android:valueType="floatType"
android:propertyName="y"
android:repeatCount="1"
android:repeatMode="reverse"/>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:repeatCount="1"
android:repeatMode="reverse">
<propertyValuesHolder android:propertyName="x" android:valueTo="400"/>
<propertyValuesHolder android:propertyName="y" android:valueTo="200"/>
</objectAnimator>
<propertyValuesHolder android:propertyName="x" >
<keyframe android:fraction="0" android:value="800" />
<keyframe android:fraction=".2"
android:interpolator="@android:anim/accelerate_interpolator"
android:value="1000" />
<keyframe android:fraction="1"
android:interpolator="@android:anim/accelerate_interpolator"
android:value="400" />
</propertyValuesHolder>
<propertyValuesHolder android:propertyName="y" >
<keyframe/>
<keyframe android:fraction=".2"
android:interpolator="@android:anim/accelerate_interpolator"
android:value="300"/>
<keyframe android:interpolator="@android:anim/accelerate_interpolator"
android:value="1000" />
</propertyValuesHolder>
使用 objectAnimaor
标签,ObjectAnimator 继承自 ValueAnimator 类,属性基本和 animaor 的定义差不多,只是多出了 android:propertyName
、android:propertyXName=""
、android:propertyYName=""
等属性,这些属性的作用就是声明属性的名称。
ObjectAnimator 对 ValueAnimator 进行了封装,一方面在创建对象时绑定了属性和目标对象,另一方面通过 Interpolator 返回当前的进度,再经过 Evaluator 根据进度计算出具体的值,最后根据属性拼接 set 函数并反射调用,并将当前值作为参数传入,实现动画,不必在监听器中监听动画进度。
代码创建对象
public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
public static ObjectAnimator ofInt(Object target, String xPropertyName, String yPropertyName,Path path)
public static ObjectAnimator ofArgb(Object target, String propertyName, int... values)
public static <T> ObjectAnimator ofArgb(T target, Property<T, Integer> property,int... values)
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
public static ObjectAnimator ofFloat(Object target, String xPropertyName, String yPropertyName,Path path)
public static ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)
ofXXX 方法内部创建了 ObjectAnimator 对象,并调用了 setXXXValues 方法,类似于 ValueAnimator,最终都是调用了 setValues 方法,在方法中给成员变量 PropertyVaulesHolder[] mValues
赋值。
ofPropertyValuesHolder 可以同时操作多个属性。
5、AnimatorSet
xml 文件定义
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially|together"
>
</set>
通过 set
标签定义,android:ordering
属性表示动画是按顺序执行还是同时执行。
public 方法
public AnimatorSet()
public void setTarget(Object target)
public void setInterpolator(TimeInterpolator interpolator)
public void playTogether(Animator... items)
public void playTogether(Collection<Animator> items)
public void playSequentially(Animator... items)
public void playSequentially(List<Animator> items)
public Builder play(Animator anim)
public void cancel()
public void end()
AnimatorSet 使用了建造者模式,内部定义了一个 Builder 类
public class Builder {
private Node mCurrentNode;
Builder(Animator anim) {
mDependencyDirty = true;
mCurrentNode = getNodeForAnimation(anim);
}
public Builder with(Animator anim) {
Node node = getNodeForAnimation(anim);
mCurrentNode.addSibling(node);
return this;
}
public Builder before(Animator anim) {
mReversible = false;
Node node = getNodeForAnimation(anim);
mCurrentNode.addChild(node);
return this;
}
public Builder after(Animator anim) {
mReversible = false;
Node node = getNodeForAnimation(anim);
mCurrentNode.addParent(node);
return this;
}
public Builder after(long delay) {
// setup dummy ValueAnimator just to run the clock
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
anim.setDuration(delay);
after(anim);
return this;
}
}
Builder 类定义了四个方法来设置动画的执行顺序,当属性动画顺序执行或指定动画执行顺序时,直接或间接调用 play 方法返回 Builder 对象控制动画的执行顺序。
监听器
AnimatorSet 内部也定义了监听器 AnimatorSetListener,类似于 Animator.AnimatorListener 监听动画开始、结束、取消、重复。
6、包装类
ObjectAnimtor 操作的属性必须要有 setXXX 方法,如果动画的时候没有传递初始值,还要有 getXXX 方法
针对上述情况,官方文档给出了三种解决方法:
- 给你的对象加上 get 和 set 方法,如果你有权限的话;
- 用一个类来包装原始对象,间接为其提供 get 和 set 方法;
这个时候目标对象就变成了包装类的对象,而原始对象成为包装类的一个成员变量,定义 set 和 get 方法设置或获取原始对象的属性值。 - 采用 ValueAnimator,监听动画过程,自己实现属性改变;
7、插值器 Interpolator
TimeInterpolator 中文翻译为时间插值器,它的作用是根据时间百分比来计算当前属性值改变的百分比,在 android.view.animation 包下面定义了 TimeInterpolator 的子接口 Interpolator,并且已经定义了十几个实现类:
在 Interpolator 的实现类里面都有一个
public float getInterpolation(float input)
方法,这个方法的参数代表动画执行时间进度的百分比,取值范围是0-1,0代表起点,1代表终点,随着动画的播放,input 从0到1逐渐变大;返回值是当前时间点对应的属性值改变的百分比,这个可以为负值,也可以大于1,为负值表示属性值小于起始值,大于1表示属性值超过终点值;
1.AccelerateInterpolator 加速插值器
该类有一个成员变量 mFractor 决定了加速的快慢
2. DecelerateInterpolator 减速插值器
3. AccelerateDecelerateInterpolator 加速减速插值器
4. LinearInterpolator 线性插值器
5. BounceInterpolator 弹跳插值器
6.AnticipateInterpolator 回荡秋千插值器
该类有一个成员变量 mTension 决定回荡幅度的大小
7. AnticipateOvershootInterpolator
8. CycleInterpolator 正弦周期变化插值器
9. OvershootInterpolator
通过上面的图像可以看出,图形的曲线表示的是属性值的变化的百分比,0表示属性起始值,1表示属性结束值,属性值主要在0~1之间变化,也可以超出该范围,曲线的斜率可以表示变化的速率
8、估值器 TypeEvaluator
插值器返回的只是属性值变化的百分比,还需要使用估值器映射出真正的属性值。
TypeEvaluator 中之定义了一个方法 evaluate ,三个参数分别为 Interpolator 返回的因子,属性的起始值和结束值。
系统中已经定义了几种实现类
看 IntEvaluator 类,evaluate 方法的返回值为**初始值 + 百分比 * (结束值 - 初始值)
各种 Evaluator 实现类的区别就在于属性值的类型的不同,有时候需要自定义 TypeEvaluator