Android 动画系列三:Propety Animation

Property Animation是android 3.0推出的另一种动画方式,能够构建线性和非线性动画,他的api被放在android.animation这个包下

在之前介绍view animation时说要比较Property Animation 和View Animation的区别,那么他们到底有哪些区别呢?

1、view animation只能够对view对象添加动画,如果要对非view对象添加动画,那么你就只能自己去实现代码了。例如:view animation

中能够对view实现scaling和rotation动画,但是却无法对背景颜色这些非view对象实现动画效果。

2、在view animation对view控件实行动画时,如果view控件的位置发生改变,这种改变是一种伪改变,如:我对一个button添加translation

动画时,在他移动的时候如果我们要触发button事件,但点击这个移动的button是无效的,无法触发事件,必须得点击他原来的位置。

3、Property animation已经成熟了,上面的那些限制都没有了,所以大多数情况下应该使用property animation,view animation就是实现起

来比property animation的代码量少一些。

通过以上比较我们就是知道了android 退出Property Animation就是为了增加新的动画功能以及取代View Animation,因为View Animation能够

做的动画Property Animation都能够做而且做的更好。所以如果你学会了Property Animation之后View Animation就可以忘记了,下面我们就来

介绍 Property Animation的用法。我们不是说Property Animation的功能已经完全替代了View Animation了吗,那么在Property Animation中去

实现View Animation的功能是怎样做的呢?

例子一:实现一个按钮被点击后能够水平缩小放大的动画(xml实现)

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:propertyName="scaleX"
    android:duration="2000"
    android:valueFrom="1.0"
    android:valueTo="2.0"
    android:repeatCount="1"
    android:repeatMode="reverse">
    
</objectAnimator>

scale = (Button)findViewById(R.id.scale);
		scale.setOnClickListener(this);
		ObjectAnimator objectScale = (ObjectAnimator)AnimatorInflater.loadAnimator(this, R.animator.objectanimator1);
		objectScale.setTarget(scale);

然后在按钮的事件监听中调用start()方法就行:objectScale.start() 这样一个简单的缩小放大的动画便完成了,那么通过Java代码怎样实现呢?

Java代码实现方法(Java代码实现方法):

object = ObjectAnimator.ofFloat(scale,"scaleX", 1.0f,2.0f);
		object.setDuration(2000);
		object.setRepeatCount(1);
		object.setRepeatMode(Animation.REVERSE);

然后在按钮的事件监听中调用start()方法:object.start() 这样通过Java代码也能够实现上面xml所实现的效果。

那么问题来了,如果我想实现多种效果混合的动画呢?在View Animation中xml实现方式我们可以通过set根元素添加多种动画效果,Java代码

则通过AnimationSet可以添加多种动画效果,那么在Property Animation是怎样实现的呢?

通过xml方式实现(xml实现)

在Property Animation中xml的实现方式也是在set根元素下添加多种动画

<?xml version="1.0" encoding="utf-8"?>
<set 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together">
    
    <objectAnimator 
	    android:propertyName="scaleX"
	    android:duration="2000"
	    android:valueFrom="1.0"
	    android:valueTo="2.0"
	    android:repeatCount="1"
	    android:repeatMode="reverse">    
	</objectAnimator>
	
    <objectAnimator 
	    android:propertyName="scaleY"
	    android:duration="2000"
	    android:valueFrom="1.0"
	    android:valueTo="2.0"
	    android:repeatCount="1"
	    android:repeatMode="reverse">    
	</objectAnimator>
    
</set>

AnimatorSet animatorSet = (AnimatorSet)AnimatorInflater.loadAnimator(this, R.animator.set1);
		animatorSet.setTarget(scale_set);

然后通过AnimatorSet将xml文件进行加载,最后在按钮的监听事件中调用start()方法:animatorSet.start()。看见没有在View Animation中是AnimationSet

类实现的在Property Animation中是AnimatorSet类实现的。

那么Java代码的方式是怎样实现的呢?(Java代码实现方法)

		set = new AnimatorSet();		
		ObjectAnimator object1 = ObjectAnimator.ofFloat(scale_set, "scaleX", 1.0f,2.0f);
		object1.setDuration(2000);
		object1.setRepeatCount(1);
		object1.setRepeatMode(Animation.REVERSE);
		
		ObjectAnimator object2 = ObjectAnimator.ofFloat(scale_set, "scaleY", 1.0f,2.0f);
		object2.setDuration(2000);
		object2.setRepeatCount(1);
		object2.setRepeatMode(Animation.REVERSE);
				
		set.playTogether(object1,object2);
		set.setDuration(2000);

然后也在按钮的事件监听中调用start()方法:set.start()。这样混合效果的动画xml实现方式以及Java代码的实现方式就讲完了。

在Java代码中除了使用ObjectAnimator和AnimatorSet来实现,还能够通过其他方法来实现动画效果

1、通过PropertyValuesHolder和ObjectAnimator实现AnimatorSet类所实现的效果

		//AnimatorSet能够实现一个对象多种动画效果,通过PropertyValuesHolder也能够实现
		//方法:先使用PropertyValuesHolder定义多种动画效果,然后将其设置进ObjectAnimator中,进而调用ObjectAnimator
		//的start()方法启动动画
		PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("scaleX", 1.0f,2.0f);
		PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleY", 1.0f,2.0f);		
		ObjectAnimator scaleAnimator = ObjectAnimator.ofPropertyValuesHolder(scale, pvhX,pvhY);
		scaleAnimator.setDuration(2000);
		scaleAnimator.setRepeatCount(1);
		scaleAnimator.setRepeatMode(Animation.REVERSE);
		scaleAnimator.start();

2、通过ViewPropertyAnimator能够实现简单的混合动画,能够简单到什么程度呢?

		ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
	    ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
	    AnimatorSet animSetXY = new AnimatorSet();
	    animSetXY.playTogether(animX, animY);
	    animSetXY.start();

	    PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
	    PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
	    ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();

上面两种实现方式用一行代码就能够实现:

		myView.animate().x(50f).y(100f);

如果要对view实现简单的Property Animation那么就可以使用这种方式,他不但高效而且可读性也强。至于具体ViewPropertyAnimator的优势在哪

里我们可以去查看android的这篇官方博客:http://android-developers.blogspot.com/2011/05/introducing-viewpropertyanimator.html

好了以上就是基本上就是Property Animation实现动画的基本实现方式,下面我们就来更深入的介绍一下Property Animation的其他方式

ValueAnimator Evaluators以及Interpolators的用法

我们知道Property Animation能够创建非线性动画,何为非线性?非线性变化频率以及变化的位置不是均匀或者直线的。

ValueAnimator是Property Animation中最要的一个类,所有的非线性动画的创建都要通过他来实现,ObjectAnimator就是继承于这个类,

ValueAnimator能够记录动画运行的时间点以及轨迹,那么他是怎样实现的这些功能的呢?他是通过封装Evaluators以及Intepolators来实现的。

Evaluators是Property Animation中3个类以及一个接口的总称,他的作用就是对给定的属性来计算当前动画的值,这个值是什么含义呢?简单理解

就是动画的状态比如你做一个淡入淡出的动画,假设动画时间2秒,那么每一时刻的动画的透明度就是通过这个接口来实现的,具体理解可以看后

面的例子再去领悟Interpolators是Property Animation中已经实现来的9个类以及一个接口的总称,那么他的具体作用是什么呢?Interpolators简称

插值器,用来计算时间的比例因子,举个例子吧,假如你要实现一个非线性的平移动画,那么你是要先加速平移然后减速平移,还是先匀速平移后

减速平移呢?Interpolators就是干这个事情的,android中以及实现了9个类了,分别是:

	1)AccelerateDecelerateInterpolator:先加速再减速。
	2)AccelerateInterpolator:一直加速。
	3)AnticipateInterpolator:先往后一下,再嗖的一声一往无前。
	4)AnticipateOvershootInterpolator:先往后一下,再一直往前超过终点,再往回收一下。
	5)BounceInterpolator:最后像个小球弹几下。
	6)CycleInterpolator:重复几次,感觉就是环形进度条那种,具体我还没试过。
	7)DecelerateInterpolator:一直减速。
	8)LinearInterpolator:线性,这个就是我们上面讲到的很均匀的了。
	9)OvershootInterpolator:到了终点之后,超过一点,再往回走。有个参数可以定义,超过的力度。

Evaluators和Interpolators都提供了接口TypeEvaluator和TimeInterpolator来供我们自定义各种状态。下面我们就来实现一个自定义的非线性动画

他实现了按钮按照贝塞尔曲线运动

public class AnimatorInterpolatorsAndEvaluator extends Activity implements OnClickListener{
	
	ValueAnimator valueAnimator;
	Button button;
	float width,height;
	ObjectAnimator object;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_animator_interpolators_and_evaluator);
		button = (Button)findViewById(R.id.button);
		button.setOnClickListener(this);
		
		DisplayMetrics metircs = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(metircs);
		width = metircs.widthPixels;
		height = metircs.heightPixels;
		
		valueAnimator = ValueAnimator.ofObject(new BezierEvaluator(), new PointF(0,0),new PointF(width,height));
		valueAnimator.setDuration(2000);
		valueAnimator.setInterpolator(new DecelerateInterpolator());//使用Interpolator对象,能够改变动画的运行速度
		valueAnimator.addUpdateListener(new AnimatorUpdateListener() {			
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				PointF pointF = (PointF)animation.getAnimatedValue();
				button.setX(pointF.x);
				button.setY(pointF.y);		
			}
		});
		valueAnimator.setTarget(button);
		valueAnimator.setRepeatCount(1);
		valueAnimator.setRepeatMode(Animation.REVERSE);
		
	}
	
	public float getInterpolation(float input) {
	    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
	}
	
	class BezierEvaluator implements TypeEvaluator<PointF>{
		
		@Override
		public PointF evaluate(float fraction, PointF startValue,
				PointF endValue) {
			final float t = fraction;
			float oneMinusT = 1.0f - t;
			PointF point = new PointF();
			
			PointF point0 = (PointF)startValue;
			
			PointF point1 = new PointF();
			point1.set(width, 0);
			
			PointF point2 = new PointF();
			point2.set(0, height);
			
			PointF point3 = (PointF)endValue;
			
			point.x = oneMinusT * oneMinusT * oneMinusT * (point0.x) 
					+ 3 * oneMinusT * oneMinusT * t * (point1.x)
					+ 3 * oneMinusT * t * t * (point2.x)
					+ t * t * t * (point3.x);
			
			point.y = oneMinusT * oneMinusT * oneMinusT * (point0.y) 
					+ 3 * oneMinusT * oneMinusT * t * (point1.y)
					+ 3 * oneMinusT * t * t * (point2.y)
					+ t * t * t * (point3.y);			
			return point;
		}
	}

	@Override
	public void onClick(View v) {
		if(v.getId() == R.id.button){
			if(valueAnimator!=null){
				valueAnimator.start();
			}	
		}
	}
}

图我不贴了,直接复制上面的代码就行了。

他的逻辑是这样的,首先我实现了TypeEvaluator接口,他实现了贝塞尔曲线是的每一点坐标值,然后将这个值返回,第二我使用了android中

一个自定义的插值器,第三利用ValueAnimator.ofObject方法创建ValueAnimator对象,将插值器对象以及Evaluator对象设置进去,第四实现

AnimatorUpdateListener接口,实现其onAnimationUpdate方法,在这个方法中将每一点的坐标值设置给按钮,然后让按钮添加动画监听。

以上就是Property Animation的全部详解了。

参考链接:http://blog.csdn.net/linmiansheng/article/details/18763987


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值