Android 动画(四)Property Animation(属性动画)
属性动画与视图动画的不同之处
- 引入时间不同:View Animation 是 API Level 1 就引入的。Property Animation 是 API Level 11 引入的,即 Android 3.0 才开始有 Property Animation 相关的 API。
- 所在包名不同:View Animation 在包 android.view.animation 中。而 Property Animation API 在包 android.animation 中。
- 动画类的命名不同:View Animation 中动画类取名都叫 XXXXAnimation,而在 Property Animator 中动画类的取名则叫 XXXXAnimator
为什么引入 Property Animator(属性动画)
1.Property Animator 能实现补间动画无法实现的功能
例如无法使用补间动画来将一个控件的背景色在一分钟内从绿色变为红色,而这个效果是可以通过 Property Animator 完美实现。
2.View Animation 仅能对指定的控件做动画,而 Property Animator 是通过改变控件某一属性值来做动画的。
补间动画和逐帧动画统称为 View Animation,也就是说这两个动画只能对派生自 View 的控件实例起作用;而 Property
Animator
则不同,从名字中可以看出属性动画是作用于控件属性的!正因为属性动画能够只针对控件的某一个属性来做动画,所以也就造就了他能单独改变控件的某一个属性的值!比如颜色!这就是
Property Animator 能实现补间动画无法实现的功能的最重要原因。
3.View Animation动画仅仅转变的是控件的显示位置而已,并没有改变控件本身的值。而Property Animator 是通过改变控件内部的属性值来达到动画效果的
View Animation 的动画实现是通过其 Parent View 实现的,在 View 被 drawn 时 Parents View
改变它的绘制参数,这样虽然 View 的大小或旋转角度等改变了,但 View
的实际属性没变,所以有效区域还是应用动画之前的区域;我们看到的效果仅仅是系统作用在按钮上的显示效果,利用动画把按钮从原来的位置移到了右下角,但按钮内部的任何值是没有变化的,所以按钮所捕捉的点击区域仍是原来的点击区域。
Property Animator框架图
一、ValueAnimator
ValueAnimator 的功能:ValueAnimator 对指定值区间做动画运算,我们通过对运算过程做监听来自己操作控件。 总而言之就是两点:
- ValueAnimator 只负责对指定的数字区间进行动画运算
- 我们需要对运算过程进行监听,然后自己对控件做动画操作
属性动画系统允许您定义动画的以下特征:
- Duration:指定动画的持续时间。默认长度为300毫秒。 Time
- interpolation:指定如何计算属性值作为动画当前已用时间的函数。
- Repeat count and behavior:指定是否在到达持续时间结束时重复动画以及重复动画的次数。您还可以指定是否要反向播放动画。将其设置为反向向前播放动画然后反复播放动画,直到达到重复次数。
- Animator sets:将动画分组为一起或按顺序或在指定延迟后播放的逻辑集。
- Frame refresh delay:指定刷新动画帧的频率。默认设置为每10毫秒刷新一次,但应用程序刷新帧的速度最终取决于系统整体的繁忙程度以及系统为基础计时器提供服务的速度。
ValueAnimator中常用方法说明:
func | explain |
---|---|
void addUpdateListener(ValueAnimator.AnimatorUpdateListener listener) | 将侦听器添加到在动画生命周期内发送更新事件的侦听器集。 |
void cancel() | 取消动画 |
void end() | 结束动画 |
void resume() | 恢复暂停的动画 |
void start() | 开始这个动画。 |
void setRepeatCount(int value) | 设置动画应重复的次数。 |
int getRepeatMode() | 定义此动画到达结尾时应执行的操作。 |
static ValueAnimator ofArgb(int… values) | 颜色动画构造函数 |
static ValueAnimator ofFloat(float… values) | 浮点动画构造函数 |
static ValueAnimator ofInt(int… values) | 整型动画构造函数 |
static ValueAnimator ofObject(TypeEvaluator evaluator, Object… values) | 对象动画构造函数 |
void setEvaluator(TypeEvaluator value) | 计算此动画的动画值时要使用的类型赋值器。 |
void removeAllUpdateListeners() | 从侦听此动画的帧更新的集中删除所有侦听器。 |
void removeUpdateListener(ValueAnimator.AnimatorUpdateListener listener) | 从侦听此动画的帧更新的集合中移除侦听器。 |
更多详见:https://developer.android.google.cn/reference/android/animation/ValueAnimator |
ValueAnimator 动画流程:
1.1 Java代码中使用方式:
开始动画:
private ValueAnimator startImageValueAnimator() {
//注意:这里的单位都是像素而不是dp
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 300);
valueAnimator.setDuration(2000);
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());//设置插值器
mStartX = ivImage01.getLeft();
//设置动画过程监听
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int) animation.getAnimatedValue();
ivImage01.layout(curValue,
ivImage01.getTop(),
ivImage01.getWidth() + curValue,
ivImage01.getBottom());
}
});
valueAnimator.start();
return valueAnimator;
}
停止动画:
private void stopImageValueAnimator(ValueAnimator animation) {
if (animation != null) {
animation.removeAllUpdateListeners();
animation.cancel();
}
}
ValueAnimator的用法比较简单,它的静态函数ofInt()表示对整型的值进行操作,参数可以传入一个或者多个值,如果传入一个值,就会从0到该值变化,多个值的话,从第一个值开始变化到第二个值,然后由第二个值变化到第三个值,依次。所以我们传进去的数字越多,动画变化就越复杂。
然后对构造好的valueAnimator 设置相关属性,然后添加动画监听器,在动画监听器中从传入的animation中获取当前的值,然后将这个值应用到需要被动画的控件中。整体流程并不复杂,但相对于Animation而言,多了一些步骤,需要写更多的代码,但它比Animation灵活多了,可以产生更多更复杂的效果,非常赞!
动画效果:
1.2 ValueAnimator xml实现方式
第一步,在res文件下新建animator文件夹,并在animator文件夹下新建anim_value_animator_test.xml文件,目录结构如下图所示:
animator/anim_value_animator_test.xml
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueFrom="0"
android:valueTo="500"
android:valueType="intType"
android:repeatCount="infinite"
android:repeatMode="reverse"/>
在java代码中通过AnimatorInflater.loadAnimator来加载anim_value_animator_test.xml
/**
* 加载xml中配置的ValueAnimator
* @return
*/
private ValueAnimator startXmlValueAnimator() {
//AnimatorInflater.loadAnimator是Android 提供的属性动画帮助类
ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.anim_value_animator_test);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int) animation.getAnimatedValue();
ivImage01.layout(curValue,
ivImage01.getTop(),
ivImage01.getWidth() + curValue,
ivImage01.getBottom());
}
});
valueAnimator.start();
return valueAnimator;
}
1.3 自定义的动画效果
其他颜色、旋转、位移、缩放等效果可以参考上面的示例实现,而我们要实现一些自定义的动画效果 怎么办呢?这时可以使用对象动画,
对象动画示例:
该例子中用到了Evaluator,如果对Evaluator不了解的话,请看Evaluator学习记录
private ValueAnimator objectValueAnimator;
/**
* 使用ofObject
*/
private void startObjectValueAnimator() {
if (objectValueAnimator != null) {
objectValueAnimator.removeAllUpdateListeners();
objectValueAnimator.cancel();
objectValueAnimator = null;
}
objectValueAnimator = ValueAnimator.ofObject(new MyAnimObjectEvaluator(), new MyAnimObject(0), new MyAnimObject(20));
objectValueAnimator.setDuration(10000);
objectValueAnimator.setInterpolator(new LinearInterpolator());
objectValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
MyAnimObject animObject = (MyAnimObject) animation.getAnimatedValue();
tvObjectText.setText("value=" + animObject.value);
LogUtil.i(TAG, "value=" + animObject.value);
}
});
objectValueAnimator.start();
}
/**
* 定义一个对象,用于存值以及传值
*/
class MyAnimObject {
public int value;
public MyAnimObject(int value) {
this.value = value;
}
}
/**
* 自定义对象动画算值器
* 返回的结果是传入值的两倍
*/
class MyAnimObjectEvaluator implements TypeEvaluator<MyAnimObject> {
@Override
public MyAnimObject evaluate(float fraction, MyAnimObject startValue, MyAnimObject endValue) {
int oldValue = startValue.value;
int newValue = endValue.value;
int res = (int) ((oldValue + newValue) * fraction) * 2;
return new MyAnimObject(res);
}
}
1.4 动画监听器
在ValueAnimator *有两个监听器:
/**
* 监听器一:监听动画变化时的实时值
*/
public static interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}
//添加方法为:public void addUpdateListener(AnimatorUpdateListener listener)
/**
* 监听器二:监听动画变化时四个状态
*/
public static interface AnimatorListener {
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}
//添加方法为:public void addListener(AnimatorListener listener)
关于监听器一:AnimatorUpdateListener 就是监听动画的实时变化状态,在 onAnimationUpdate(ValueAnimator animation)中的 animation 表示当前状态动画的实例。这里就不再细讲这个监听器了,这里我们主要讲讲监听器 AnimatorListener; 在 AnimatorListener 中,主要是监听 Animation 的四个状态,start、end、cancel、repeat;当动画开始时,会调用 onAnimationStart(Animator animation)方法,当动画结束时调用 onAnimationEnd(Animator animation),当动画取消时,调用 onAnimationCancel(Animator animation)函数,当动画重复时,会调用 onAnimationRepeat(Animator animation)函数。 添加 AnimatorListener 的方法是 addListener(AnimatorListener listener) ;
1.5 取消监听:
/**
* 移除 AnimatorUpdateListener
*/
void removeUpdateListener(AnimatorUpdateListener listener);
void removeAllUpdateListeners();
/**
* 移除 AnimatorListener
*/
void removeListener(AnimatorListener listener);
void removeAllListeners();
剩下的ObjectAnimator以及AnimatorSet会在后续博文中学习记录。
上一篇: ZProperty属性封装类简介
下一篇: Python中property的原理
推荐阅读
-
Android Animation之TranslateAnimation(平移动画)
-
图文详解Android属性动画
-
Android 四种动画效果的调用实现代码
-
Android开发之图形图像与动画(二)Animation实现图像的渐变/缩放/位移/旋转
-
Android开发之图形图像与动画(四)AnimationListener简介
-
Android开发之图形图像与动画(三)Animation效果的XML实现
-
基于CSS3 animation动画属性实现轮播图效果
-
CSS3与动画有关的属性transition、animation、transform对比(史上最全版)
-
Android 属性动画ValueAnimator与插值器详解
-
Android 四种动画效果的调用实现代码