关闭

属性动画(Property Animation)的使用

标签: Property Animation属性动画
664人阅读 评论(0) 收藏 举报

属性动画与补间动画最大的区别就是,控件通过属性动画改变位置后,控件的位置会随着改变,而补间动画控件还是在原地。


属性:

Duration:动画持续时间,默认持续时间为300ms

Time Interpolation:时间差值,与补间动画的Interpolation相似,即改变动画执行速度

Repeat count and behavior:重复次数及模式

Animator sets:动画集合

Frame refresh delay:多久刷新一次帧,默认10ms,依赖系统执行的状态


相关类:

ObjectAnimator:动画的执行类

ValueAnimator:动画的执行类

AnimatorSet:动画集合

AnmatorInflater:加载文件夹为animator的xml文件

TypeEvaluator:类型估值,主要用于设置动画操作属性的值

TimeInterpolator:时间差值


以下是代码的应用:

package com.example.propertyanimation;

import android.os.Bundle;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.IntEvaluator;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.PointF;
import android.view.View;
import android.view.ViewGroup.LayoutParams;

@SuppressLint("NewApi")
public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}
	
	/**
	 * xml绑定标签
	 * @param v
	 * x方向上旋转的动画效果
	 */
	public void a(View v) {
		//属性动画的动画执行类
		/**
		 * @parm target-->要操作的属性的对象(如果为T类型则是泛型,Object所有类型)
		 * @parm property-->要操作的属性的名称,即v对象的set方法中的属性都可以改变
		 * @parm values-->改变该属性的值
		 */
		ObjectAnimator animator = ObjectAnimator.ofFloat(v, "rotationX", 0,360.0f,0);//从0-->360-->0
		animator.setDuration(3000);//执行时间
		animator.start();//启动动画
	}
	
	/**
	 * 同时设置多个属性的动画效果
	 * 透明度从0到1,拉伸从0到1再拉伸到2倍(变化的趋势一样)
	 */
	public void b(final View v) {
		/*
		 * 方法1
		 */
//		ObjectAnimator animator = ObjectAnimator.ofFloat(v, "", 0,1);
//		animator.setDuration(5000);
//		animator.start();
//		//添加在更新时的监听事件
//		animator.addUpdateListener(new AnimatorUpdateListener() {
//			//每次动画刷新的时候就会执行该方法
//			@Override
//			public void onAnimationUpdate(ValueAnimator arg0) {
//				//此次刷新时改变的值
//				float value = (Float) arg0.getAnimatedValue();
//				v.setAlpha(value);
//				float scaleX = 2 * value;//拉伸到2倍
//				v.setScaleX(scaleX);
//				v.setScaleY(scaleX);
//			}
//		});
		
		/*
		 * 方法2
		 */
		PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("scaleX", 0,2);
		PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleY", 0,2);
		PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("alpha", 0,1);
		//同时在v上设置三个动画效果,参数2为可变参数
		ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(v, holder1,holder2,holder3);
		animator.setDuration(5000);
		animator.start();
	}
	
	/**
	 * 设置控件的宽高
	 */
	public void c(final View v) {
//		Button button;
//		button.setWidth(pixels)//不是设置控件宽度,是设置控件的最大宽度
		ObjectAnimator animator = ObjectAnimator.ofFloat(v, "", 0, 200);
		animator.setDuration(4000);
		animator.start();
		//若改变的属性没有set方法,可以在监听事件中进行修改
		animator.addUpdateListener(new AnimatorUpdateListener() {
			
			@Override
			public void onAnimationUpdate(ValueAnimator arg0) {
				float value = (Float) arg0.getAnimatedValue();
				/**
				 * 改变控件的宽高
				 */
				//获取布局参数
				LayoutParams params = v.getLayoutParams();//统一的父类ViewGroup,所以不用强转
				params.width = (int) value;
				params.height = (int) value;
				v.requestLayout();//请求布局,刷新布局参数,一般使用这个。只要布局改变了调用这个方法都有效果
//				v.setLayoutParams(params);
			}
		});
	}
	
	
	/**
	 * 使用类型估值(TypeValue)设置控件的宽高
	 */
	public void d(final View v) {
		final int width = v.getWidth();
		ObjectAnimator animator = ObjectAnimator.ofFloat(v, "", 1, 100);
		animator.setDuration(4000);
		animator.start();
		//若改变的属性没有set方法,可以在监听事件中进行修改
		animator.addUpdateListener(new AnimatorUpdateListener() {
			
			@Override
			public void onAnimationUpdate(ValueAnimator arg0) {
				float value = (Float) arg0.getAnimatedValue();//获取每次改变的值
//				FloatEvaluator
				IntEvaluator intEvaluator = new IntEvaluator();//获取类型估值对象
				/**
				 * 改变控件的宽高
				 */
				//获取布局参数
				LayoutParams params = v.getLayoutParams();//统一的父类ViewGroup,所以不用强转
				//每次改变的值为:(200-width)/100
				//方法1
//				params.width = (int) (width + value*(200-width)/100);//目的:每次变化的值都一样,不管控件的大小是多少
				//参数1每次改变的值(每次改变的比例),参数2为起始的值,参数3为结束的值
				//参数1已经写好了:(结束的值-起始的值)*value
				params.width = intEvaluator.evaluate(value/100, width, 200);
				params.height = (int) value;
				v.requestLayout();
			}
		});
	}
	
	/**
	 * 类型估值的应用
	 */
	public void e(final View v) {
		//让控件随着设置的点移动,PointF浮点数坐标
		TypeEvaluator<PointF> evaluator = new TypeEvaluator<PointF>() {
			
			/**
			 * 估算每次移动时的位置
			 * @param arg0 -->此次变化的比例
			 * @param arg1 -->最开始的时候的位置
			 * @param arg2 -->最后的位置
			 * @return
			 */
			@Override
			public PointF evaluate(float arg0, PointF arg1, PointF arg2) {
				PointF pointF = new PointF();
				pointF.x = (arg2.x-arg1.x)*arg0+arg1.x;
				pointF.y = (arg2.y-arg1.y)*arg0+arg1.y;
				return pointF;
			}
		};
		PointF start = new PointF(v.getLeft(), v.getTop());//起始的位置
		PointF end = new PointF(200, 200);//结束的位置
		ObjectAnimator objectAnimator = ObjectAnimator.ofObject(v, "", evaluator, start,end);
		objectAnimator.addUpdateListener(new AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator arg0) {
				PointF pointF = (PointF) arg0.getAnimatedValue();
				v.setX(pointF.x);
				v.setY(pointF.y);
			}
		});
	objectAnimator.setDuration(1000);
	objectAnimator.start();
	}
	
	/**
	 * ValueAnimtor
	 */
	public void f(final View v) {
		ValueAnimator animator = new ValueAnimator();
		//设置动画变化的值
		animator.setFloatValues(0,360,0);
		animator.addUpdateListener(new AnimatorUpdateListener() {
			
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				float value = (Float) animation.getAnimatedValue();
				v.setRotationX(value);
			}
		});
		animator.setDuration(1000);
		animator.start();
	}
	
	/**
	 * 监听动画状态
	 */
	public void g(View v) {
		ValueAnimator valueAnimator = new ValueAnimator();
		
//		valueAnimator.cancel();//取消动画
		/**
		 * 状态变化时就会执行
		 */
		valueAnimator.addListener(new AnimatorListener() {
			//开始动画的状态
			@Override
			public void onAnimationStart(Animator animation) {
			}
			//重复的状态
			@Override
			public void onAnimationRepeat(Animator animation) {
			}
			//动画结束的时候
			@Override
			public void onAnimationEnd(Animator animation) {
			}
			//动画取消的状态,即调用cancel()方法时才会调用
			@Override
			public void onAnimationCancel(Animator animation) {
			}
		});
		
		/**
		 * 监听动画的状态
		 * 添加AnimatorListenerAdapter监听事件,按照需要重写需要监听的动画状态的方法
		 */
		//AnimatorListenerAdapter抽象类,方法都已经重写,但是方法体都是空的
		valueAnimator.addListener(new AnimatorListenerAdapter() {
			@Override
			public void onAnimationStart(Animator animation) {
				super.onAnimationStart(animation);
			}
		});
	}
	
	/**
	 * AnimatorSet
	 * 动画的集合
	 */
	public void h() {
		ValueAnimator v1 = new ValueAnimator();
		ValueAnimator v2 = new ValueAnimator();
		ValueAnimator v3 = new ValueAnimator();
		
		AnimatorSet animatorSet = new AnimatorSet();
		//播放v1和v2一起
		animatorSet.play(v1).with(v2);
		//播放v3在v2之后
		animatorSet.play(v3).after(v2);
		//全部一起播放
		animatorSet.playTogether(v1,v2,v3);
		//按顺序播放,写前面的先播放
		animatorSet.playSequentially(v1,v2,v3);
		//每一个动画执行的时间
		animatorSet.setDuration(1000);
		animatorSet.start();
	}
	
	/**
	 * xml中设置属性动画
	 */
	public void i(View v) {
		Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object);
		//设置操作的控件
		animator.setTarget(v);
		animator.start();
	}

}

xml文件如下:

值得注意的是属性动画的res下的文件夹应该是animator

<?xml version="1.0" encoding="utf-8"?>

<!--propertyName:属性  -->
<!--valueType:变化值的类型  -->
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" 
    android:valueType="floatType"
    android:valueFrom="0"
    android:valueTo="360"
    android:propertyName="rotationX">
    

</objectAnimator>


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:18017次
    • 积分:427
    • 等级:
    • 排名:千里之外
    • 原创:26篇
    • 转载:5篇
    • 译文:0篇
    • 评论:0条