版权声明:本文为博主原创文章,未经博主允许不得转载。
http://blog.csdn.net/jjwwmlp456/article/details/38518657
- Property Animation介绍
- 3.0以后新增了一些View的属性
- ObjectAnimator 对象动画
- AnimatorSet 动画集
- PropertyValuesHolder
- ViewPropertyAnimator 多属性动画
- ValueAnimator 值动画
- Animator的监听器
- 用属性动画换背景色
- LayoutTransition
效果图:
Property Animation介绍:
出生在sdk3.0,是利用了View所拥有的属性,进行一系列的操作。比如一个View有什么样的setAbc的属性,那么理论上就可以设置它。
它不仅改变View的绘制,也改变了View的属性;而Tween Animation 只改变View的绘制。
Animator为属性动画的基类
其结构:
Animator abstract class
---- AnimatorSet final class 属性动画的集合,可以添加下面的值动画和对象对象在其内,可同时运行或顺序运行
----ValueAnimator 值动画。监听某一值的变化,进行相应的操作
---- ObjectAnimator final class 对象动画
ValueAnimator 值动画,它有一个子类ObjectAnimator。需要Interpolator和TypeEvaluator来计算属性值。
TimeInterpolator 时间插入器 接口,反应动画的运动速率。getInterpolation()根据一定算法,返回时间比率
----Interpolator interface 继承自TimeInterpolator
Interpolator 接口的实现类 见下表:
xml 设置 插入器:android:interpolator="@android:anim/accelerate_decelerate_interpolator"
TypeEvaluator<T> interface 计算类型值 支持泛型
方法:T evaluate(float fraction, T startValue, T endValue)
就是用来计算属性值的,即可计算任意类型的值。
fraction 表示时间的比率。
实现类有: ArgbEvaluator ARGB颜色计算器
FloatEvaluator float型计算器
IntEvaluator int计算器
PropertyValuesHolder 属性值持有者 持有属性名、开始与结束值。
属性设置方法:setIntValues()、setFloatValues()、setObjectValues()、setKeyframes
它的静态的一些of方法,创建 PropertyValuesHolder 对象。 ofInt、ofFloat、ofObject、ofKeyframe
setEvaluator(eval); //设置计算器。
Keyframe 表示 a time/frame-value pair. 即含有 时间比率和帧值 属性
它的静态的一些of方法,创建 Keyframe 对象。 ofInt、ofFloat、ofObject
KeyframeSet 就是一组KeyFrame
它的静态的一些of方法,创建 KeyframeSet 对象。 ofInt、ofFloat、ofObject、ofKeyframe
[plain] view plaincopyprint?
- 属性动画的一些说明:
- 1. ObjectAnimator 对象动画,当一个view同时拥有某一属性的getter、setter方法时,则可以使用该动画,来操作这一属性。
- 2. ValueAnimator 操作的范围比较广,通过Interpolator和TypeEvaluator得到某一时间内的值;再用监听器,监听值的变化,做相应的操作。
- 3. ValueAnimator 和ObjectAnimator(它是前者的子类)的静态的一些of方法,创建自身对象。
- 也可以new 一个无参的对象,再设置相应的values。
- ofInt()、ofFloat()、ofObject()、ofPropertyValuesHolder()。
- 这几个方法的实现也就是new 一个无参的对象,再设置相应的values。
- 4. ValueAnimator 的调用流程:
- a. 初始化ValueAnimator后,设置一个values。这时就有了一个PropertyViewHolder对象pvh。
- 可以直接调用setValues设置它PVH对象;或setInt|Float|ObjectValues
- 方法内部会生成一个PVH
- PVH内部维护一个KeyframeSet和TypeEvaluator。PVH根据不同的values来初始化KeyframeSet和
- TypeEvaluator实现方法中的startValue和endValue就从KeyframeSet中的Keyframe中获取
- b. 设置TypeEvaluator,传递到pvh中。
- c. 设置Interpolator。 ValueAnimator中默认的插入器为AccelerateDecelerateInterpolator
- d. ValueAnimator的animationFrame(long currentTime),当有动画应该结束时返回true,否则返回false。
- 方法内,算出动画运行的时间比率fraction,再调用animateValue(float fraction)。
- e. ValueAnimator的animateValue(float fraction),调用插入器,得到一个按某一规则得到的fraction,
- 再调用 pvh.calculateValue(fraction);pvh调用KeyframeSet的getValue(fraction);
- KeyframeSet内部再调用TypeEvaluator的evaluate(fraction,T startValue, T endValue)。
- startValue、endValue是通过Keyframe的getValue()来获取的。
- f. evaluate(),方法内拿到了时间比率fraction,可以自行根据一定规则,返回value T。
- g. 给ValueAnimator添加一个AnimatorUpdateListener。监听的回调方法:
- onAnimationUpdate(ValueAnimator animation) {
- T obj = (T)animation.getAnimatedValue();//取得计算器计算出的某段时间内的T值。
- // 操作 obj
- }
先来一个使用自定义类型的求值计算器的ValueAnimator的例子
[java] view plaincopyprint?
- ValueAnimator backAnim;
- ImageView view;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.aa);
- view = (ImageView) findViewById(R.id.iv_img);
- backAnim = new ValueAnimator();
- backAnim.setTarget(view);
- backAnim.setDuration(2000);
- //类型求值<Drawable>:求出某一时间比值内的Drawable值
- TypeEvaluator<Drawable> drawableEvaluator = new TypeEvaluator<Drawable>() {
- @Override //fraction 当前运行的时间比上总持续时间的 比值(中间经过插入器的规则运算)
- public Drawable evaluate(float fraction, Drawable startValue,
- Drawable endValue) {
- System.out.println(fraction);
- if (fraction < 0.5) {
- return startValue;
- } else {
- return endValue;
- }
- }
- };
- //可以直接设置PVH对象;也可以先设置values,再设置TypeEvaluator
- // PropertyValuesHolder pvh = PropertyValuesHolder.ofObject("imageDrawable", drawableEvaluator,
- // getResources().getDrawable(R.drawable.ic_launcher), getResources().getDrawable(R.drawable.a1));
- // backAnim.setValues(pvh);
- backAnim.setObjectValues(getResources().getDrawable(R.drawable.ic_launcher), getResources().getDrawable(R.drawable.a2));
- backAnim.setEvaluator(drawableEvaluator);
- backAnim.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- Drawable value = (Drawable) animation.getAnimatedValue();
- view.setImageDrawable(value);
- }
- });
- backAnim.setInterpolator(new CycleInterpolator(2));
- backAnim.start();
- }
3.0以后新增了一些View的属性:
1)translationX 和 translationY:这两个属性控制了View所处的位置,
它们的值是由layout容器设置的,是相对于坐标原点(0,0左上角)的一个偏移量。
2)rotation, rotationX 和 rotationY:控制View绕着轴点(pivotX和pivotY)旋转。它的表现跟Tween Animation中的RotateAnimation不一致。
RotateAnimation 的旋转,表现为平面的旋转
而rotationX、Y 旋转,是立体的旋转,默认是以View的中心点,做rotation(x,y)过中心点的直线,面向该直线进行翻转
3)scaleX 和 scaleY:控制View基于pivotX和pivotY的缩放。
4)pivotX 和 pivotY:旋转的轴点和缩放的基准点,默认是View的中心点。
5)x 和 y:描述了view在其父容器中的最终位置,是左上角坐标和偏移量(translationX,translationY)的和。
6)aplha:透明度,1是完全不透明,0是完全透明。
以上这些属性与Tween Animation的动画属性值差不多
ObjectAnimator 对象动画
该动画,一次只能表示一个动作属性。
ObjectAnimator的xml实现
xml定义动画
res/animator/scale_object_animator.xml
[html] view plaincopyprint?
- <?xml version="1.0" encoding="utf-8"?>
- <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:duration="2000"
- android:propertyName="scaleX"
- android:repeatCount="1"
- android:repeatMode="reverse"
- android:valueFrom="1.0"
- android:valueTo="2.0" >
- </objectAnimator>
代码加载 动画xml
[java] view plaincopyprint?
- imageview_scale.setBackground(getResources().getDrawable(R.drawable.a11));
- ObjectAnimator scaleAnimator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.scale_object_animator);
- scaleAnimator.setTarget(imageview_scale);//设置动画作用的目标对象
- scaleAnimator.setDuration(1000);
- scaleAnimator.setRepeatCount(50);
- scaleAnimator.start();
AnimatorSet 动画集
由ObjectAnimator 和 ValueAnimator 组成,对应的xml中的写法 类似为 <set> <objectAnimator /> ... <animator />... </set>
xml定义动画集
res/animator/set_rotate_scale.xml
[html] view plaincopyprint?
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android"
- android:ordering="together">
- <!-- android:ordering together表示同时运行动画, sequentially 表示按顺序执行以下动画 -->
- <set>
- <objectAnimator
- android:propertyName="rotationX"
- android:repeatCount="50"
- android:repeatMode="reverse"
- android:valueFrom="0"
- android:valueTo="20" />
- <objectAnimator
- android:propertyName="rotationY"
- android:repeatCount="50"
- android:repeatMode="reverse"
- android:valueFrom="0"
- android:valueTo="45"
- android:valueType="floatType" />
- </set>
- <set>
- <objectAnimator
- android:propertyName="scaleX"
- android:repeatCount="50"
- android:repeatMode="reverse"
- android:valueFrom="1.0"
- android:valueTo="2.0" >
- </objectAnimator>
- <objectAnimator
- android:propertyName="scaleY"
- android:repeatCount="50"
- android:repeatMode="reverse"
- android:valueFrom="1.0"
- android:valueTo="2.0" >
- </objectAnimator>
- </set>
- </set>
代码加载 动画集的xml
[java] view plaincopyprint?
- imageview_rotate.setBackground(getResources().getDrawable(R.drawable.a11));
- AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.set_rotate_scale);
- animatorSet.setTarget(imageview_rotate);
- animatorSet.setDuration(1000);
- animatorSet.setInterpolator(new BounceInterpolator());//设置end时的弹跳插入器
- animatorSet.start();
PropertyValuesHolder
[java] view plaincopyprint?
- //使用PropertyValuesHolder 构造 Animator 组合成类似set的效果
- PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("scaleX",0f,2.5f);
- PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleY",0f,3f);
- ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(imageview, pvhX,pvhY);
- animator.setDuration(2000);
- animator.start();
APIDemo中的MultiPropertyAnimation示例:
[java] view plaincopyprint?
- // ============================================================
- // 第四个小球:利用关键帧实现曲线运动
- ball = balls.get(3);
- // 属性1:Y坐标运动:下落
- pvhY = PropertyValuesHolder.ofFloat("y", ball.getY(),
- getHeight() - BALL_SIZE);
- float ballX = ball.getX();
- // 三个关键帧
- Keyframe kf0 = Keyframe.ofFloat(0f, ballX); //参数为 time/value, 即时间点和指定值。还有这些构造ofInt()、ofObject()
- Keyframe kf1 = Keyframe.ofFloat(.5f, ballX + 100f);
- Keyframe kf2 = Keyframe.ofFloat(1f, ballX + 50f);
- // 属性2:X坐标运动:曲折
- // 用三个关键帧构造PropertyValuesHolder对象
- PropertyValuesHolder pvhX = PropertyValuesHolder.ofKeyframe(
- "x", kf0, kf1, kf2);
- // 再用两个PropertyValuesHolder对象构造一个ObjectAnimator对象。<span style="color:#ff6666;">一个holder持有一个属性</span>
- ObjectAnimator yxBouncer = ObjectAnimator
- .ofPropertyValuesHolder(ball, pvhY, pvhX).setDuration(
- DURATION / 2);
- yxBouncer.setRepeatCount(1);
- yxBouncer.setRepeatMode(ValueAnimator.REVERSE);
ViewPropertyAnimator 多属性动画
通过view.animate()来获取ViewPropertyAnimator。该类,能直接操作多个属性的动画。
[java] view plaincopyprint?
- imageview.setBackground(getResources().getDrawable(R.drawable.a11));
- ViewPropertyAnimator animate = imageview.animate();//该对象没有setRepeat的方法
- //通过一些动画属性来设置 组合成类似set的效果
- animate.alpha(0);
- animate.rotationX(50);
- animate.translationXBy(500);
- animate.scaleX(1.5f);
- animate.scaleY(1.5f);
- animate.setInterpolator(new BounceInterpolator());
- animate.setDuration(2000);
- animate.start();
ValueAnimator 值动画
ValueAnimator代码和xml设置中 没有setPropertyName 因为不是操作对象,只是根据value进行某种动作
需要加监听器,监听值的变化 做相应的处理
xml定义值动画
[html] view plaincopyprint?
- <?xml version="1.0" encoding="utf-8"?>
- <animator xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/accelerate_interpolator"
- android:duration="10000"
- android:startOffset="1000"
- android:repeatCount="infinite"
- android:repeatMode="restart"
- android:valueFrom="1"
- android:valueTo="100"
- android:valueType="intType">
- </animator>
代码加载 值动画xml
[java] view plaincopyprint?
- ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator);
- valueAnimator.setTarget(tv_num);
- valueAnimator.setEvaluator(new TypeEvaluator<Integer>() {
- @Override
- public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
- System.out.println("时间比率,fraction:" + fraction);
- System.out.println("结果值:" + (int)((startValue + fraction * (endValue - startValue)) / 10 * 10));
- return (int)((startValue + fraction * (endValue - startValue)) / 10 * 10);
- }
- });
- valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- //在onAnimationUpdate中 该值返回第一个动画的 当前帧的evaluate 值
- System.out.println("animation.getAnimatedValue()==" + animation.getAnimatedValue());
- tv_num.setText(animation.getAnimatedValue() + "");
- }
- });
- // valueAnimator.setInterpolator(new LinearInterpolator());
- valueAnimator.start();
Animator的监听器
AnimatorListener
[java] view plaincopyprint?
- new AnimatorListener() {//有以下四个抽象方法
- @Override
- public void onAnimationStart(Animator animation) {
- }
- @Override
- public void onAnimationRepeat(Animator animation) {
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- }
- @Override
- public void onAnimationCancel(Animator animation) {
- }
- }
AnimatorListenerAdapter 监听器的默认空实现
[java] view plaincopyprint?
- new AnimatorListenerAdapter() {//空实现了AnimatorListener,有以下6个方法(4个必须实现的方法和2个重写的方法)
- @Override
- public void onAnimationCancel(Animator animation) {
- super.onAnimationCancel(animation);
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- }
- @Override
- public void onAnimationRepeat(Animator animation) {
- super.onAnimationRepeat(animation);
- }
- @Override
- public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
- }
- @Override
- public void onAnimationPause(Animator animation) {
- super.onAnimationPause(animation);
- }
- @Override
- public void onAnimationResume(Animator animation) {
- super.onAnimationResume(animation);
- }
- }
AnimatorUpdateListener 动画的值更新监听器
[java] view plaincopyprint?
- new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- //在onAnimationUpdate中 该值返回第一个动画的 当前帧的evaluate 值
- System.out.println("animation.getAnimatedValue()==" + animation.getAnimatedValue());
- }
- }
一些操作函数:
animator.pause(); animator.resume(); animator.reverse(); animator.end(); animator.cancel();
animator.start(); animator.isStarted(); animator.isPaused(); animator.isRunning();
用属性动画换背景色
详见ApiDemo要下的 BouncingBalls.java
[java] view plaincopyprint?
- private static final int RED = 0xffFF8080;
- private static final int BLUE = 0xff8080FF;
- private static final int CYAN = 0xff80ffff;
- private static final int GREEN = 0xff80ff80;
- {
- //动画 变色
- ObjectAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", CYAN, BLUE, RED);
- colorAnim.setTarget(ll_animation);
- colorAnim.setEvaluator(new ArgbEvaluator());
- colorAnim.setRepeatCount(ValueAnimator.INFINITE);
- colorAnim.setRepeatMode(ValueAnimator.REVERSE);
- colorAnim.setDuration(3000);
- colorAnim.start();
- }
LayoutTransition
[java] view plaincopyprint?
- /*
- * ViewGroup中使用LayoutTransition 进行 监听布局的改变,而创建动画
- * LayoutTransition.APPEARING 新增出现时
- * CHANGE_APPEARING
- * CHANGE_DISAPPEARING 子view消失时
- * CHANGING
- * ViewGroup布局中:android:animateLayoutChanges="true" 使用的默认的LayoutTransition制作动画
- */
- LayoutTransition layoutTransition = new LayoutTransition();
- layoutTransition.setDuration(5000);
- layoutTransition.setAnimator(LayoutTransition.APPEARING, scaleAnimator);
- ll_animation.setLayoutTransition(layoutTransition);
- final TextView tv = new TextView(this);
- tv.setWidth(100);
- tv.setHeight(100);
- tv.setText("中华人民共和国");
- ll_animation.addView(tv);//对应type = APPEARING
- ll_animation.postDelayed(new Runnable() {
- @Override
- public void run() {
- ll_animation.removeView(tv);
- }
- }, 2000);