Android属性动画简析

简析

大家知道,我们在开发一款产品的时候为了达到良好的用户体验,我们可以在应用中适当的加上一些动画效果,譬如平移、缩放、旋转等等,但是这些常用的动画在Android很早期的版本中就存在了,我们称之为传统动画,传统动画一般分为Tween动画和Frame动画,这也是我们最常用的的动画,统称为Animation。传统的Animation动画实现上是通过不停的调用View的onDraw方法来重新绘制View来实现的。

在Android3.0以后,Google为Android新增了属性动画框架Animator,为什么叫做属性动画呢?因为属性动画Animator不像传统动画那样需要不停调用onDraw方法绘制界面,而且可以通过get、set方法,去真实的改变一个view的属性的。Animation动画仅仅给用户一种“虚假”的动画效果,其执行动画view并没有正在的改变自身的属性,例如位置。而属性动画Animator,是真真正正的通过代码将view“动画”到了指定的位置了。

传统动画不能改变view真实属性

下面,我们来看看传统动画实现的效果,我们使用很简单的界面,给指定的ImageView设置上平移动画,给ImageView指定点击事件监听,方便我们测试传统动画的局限性。

public class MainActivity extends Activity {

	private Button mButton;
	private ImageView mImageView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		mButton = (Button) findViewById(R.id.button);
		mImageView = (ImageView) findViewById(R.id.imageview);

		mButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				playAnim();
			}
		});
		mImageView.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showToast();
			}
		});
	}

	/**
	 * 播放动画
	 */
	protected void playAnim() {
		TranslateAnimation ta = new TranslateAnimation(0.0f, 200.0f, 0.0f, 0.0f);
		ta.setDuration(1000);
		ta.setFillAfter(true);
		mImageView.startAnimation(ta);
	}

	protected void showToast() {
		Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_SHORT).show();
	}

}

看到运行效果了吧,我们给ImageView的小机器人设置了点击事件并且弹出Toast了,当我们点击Button时,ImageView上的平移动画被执行了,并且平移到了指定的位置(200px),然而我们在此时的ImageView上点击时,并没有弹出Toast提示,也就是说点击的位置不在那里,当我回头再次点击ImageView最初的位置时,Toast又被show了出来,这是不是很“诡异”?是的,上面的小例子足以说明,传统的Animaion动画只能改变动态视觉效果的动画,并不能真实的去改变一个View的属性(位置等)。而且,传统的Animation动画是通过不停的调用onDraw方法去绘制而完成的效果,这样的实现方式很消耗资源(cpu)的。

API概述

描述
ValueAnimator 属性动画时序引擎也计算属性动画的值。它拥有所有的核心功能,计算动画值,并包含每个动画,有关时序的详细信息是否动画重复,听众接收更新事件,并设置自定义类型的能力评估。有两件,以生动活泼的属性:动画值计算和设置这些对象的属性动画值。ValueAnimator不进行第二件,所以你一定要更新计算值ValueAnimator和修改你想用自己的逻辑动画的对象。
ObjectAnimator ValueAnimator的子类,允许你设置一个目标对象和对象属性的动画。当计算出一个新的动画值,本类更新相应的属性。你大部分情况使用ObjectAnimator,因为它使得动画的目标对象的值更简单。然而,有时你直接使用ValueAnimator,因为ObjectAnimator有一些限制,如对目标对象目前要求的具体acessor方法。
AnimatorSet 提供机制,以组合动画一起,让他们关联性运行。你可以设置动画一起播放,顺序,或在指定的延迟之后。

内容来自于:http://developer.android.com/guide/topics/graphics/prop-animation.html

ObjectAnimator

执行单个动画

通常我们会使用ObjectAnimator类来为我们的view设置动画,下面我们来简单的看一下,使用了属性动画后,我们上述的小例子中的ImageView会发生哪些变化?修改上面的playAnim方法,将普通动画换成属性动画:

protected void playAnim() {
		ObjectAnimator.ofFloat(mImageView, "translationX", 0.0f, 200.0f).setDuration(1000).start();
}

运行效果如上图所示。对比上面的那幅图看,发现当属性动画执行后,不但从视觉上改变了ImageView的位置,而且ImageView上的点击事件的位置也跟着变化了,说明使用属性动画的View,实际上是真实的改变了一个View的属性的。

从上面的一行代码中,可以发现属性动画使用上是非常简单的,ObjectAnimator中的ofFloat方法实际上是static方法,而且返回值还是一个ObjectAnimator对象。ofFloat的参数也很简单,第1个参数是指定需要执行动画的view,第2个参数是动画模式,第三个参数是可变的数组,这里需要描述动画的初始位置和终点位置的坐标。

除了上面例子的中的translationX属性,还可以指定translationY属性,表示ImageView沿着Y轴的方向平移,然后我们也可以指定X或者Y,那么translationX和X或者translationY和Y的区别,就是translationX是指定了ImageView在X轴上的偏移量,而单纯的指定X表示ImageView被移动到指定的X轴上的位置,这点跟View的scrollTo和scrollBy方法有点类似。此外除了平移之外,还可以指定动画的模式有:

translationX、translationY

rotation、rotationX、rotationY

scaleX、scaleY

X、Y

alpha

ObjectAnimator继承自ValueAnimator,要指定一个对象及该对象的一个属性,当属性值计算完成时自动设置为该对象的相应属性,即完成了Property Animation的全部两步操作。实际应用中一般都会用ObjectAnimator来改变某一对象的某一属性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,应该满足以下条件:

  • 对象应该有一个setter函数:set<PropertyName>(驼峰命名法)
  • 如上面的例子中,像ofFloat之类的工场方法,第一个参数为对象名,第二个为属性名,后面的参数为可变参数,如果values…参数只设置了一个值的话,那么会假定为目的值,属性值的变化范围为当前值到目的值,为了获得当前值,该对象要有相应属性的getter方法:get<PropertyName>
  • 如果有getter方法,其应返回值类型应与相应的setter方法的参数类型一致。

如果上述条件不满足,则不能用ObjectAnimator,应用ValueAnimator代替。

多个动画同时执行

PropertyValuesHolder

有时候我们需要同时执行多个属性动画的叠加效果的时候,可以使用PropertyValuesHolder工具类来“装载”多种动画,然后调用ObjectAnimator.ofPropertyValuesHolder()方法将装载好的动画交给ObjectAnimator去执行,例如:

protected void playAnim() {
		PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationX",0.0f, 200.0f);
		PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("translationY",0.0f, 200.0f);
		PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("rotation",0.0f, 360.0f);
		ObjectAnimator.ofPropertyValuesHolder(mImageView, p1, p2, p3).setDuration(2000).start();
}

AnimatorSet

跟普通的View动画一样,执行多种动画效果时,属性动画也提供了动画集方便我们执行多种动画。

protected void playAnim() {
		Animator animator1 = ObjectAnimator.ofFloat(mImageView, "translationX",0.0f, 200.0f);
		Animator animator2 = ObjectAnimator.ofFloat(mImageView, "translationY",0.0f, 200.0f);
		Animator animator3 = ObjectAnimator.ofFloat(mImageView, "rotation",0.0f, 360.0f);
		AnimatorSet set = new AnimatorSet();
		set.playTogether(animator1, animator2, animator3);
		set.setDuration(2000);
		set.start();
}

AnimationSet提供了一个把多个动画组合成一个组合的机制,并可设置组中动画的时序关系,如同时播放,顺序播放等。

以下例子同时应用5个动画:

  1. 播放anim1;
  2. 同时播放anim2,anim3,anim4;
  3. 播放anim5。
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(anim1).before(anim2);
bouncer.play(anim2).with(anim3);
bouncer.play(anim2).with(anim4)
bouncer.play(anim5).after(amin2);
animatorSet.start();

动画监听事件

Android属性动画也为我们提供了对动画播放过程的监听器,我们只需要调用Animator.addListener()方法,将AnimatorListener对象传递进去就可以了:

anim.addListener(new Animator.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) {
		//动画被取消时执行
	}
});

Animator.AnimatorListener对象下,有4个未实现的方法,我们可以分别实现一下其中的方法,就可以方便的去监听动画执行整个过程了。但是Animator.AnimatorListener对象不够简洁,因为大部分时候我们只需要监听动画结束时的事件即可,那么Android也为我们提供好了一个简化的监听对象AnimatorListenerAdapter,AnimatorListenerAdapter

是个抽象类,其下面共有onAnimationCancel(),onAnimationEnd(),onAnimationPause(),onAnimationRepeat(),onAnimationResume(),onAnimationStart()几个方法供我们调用,既然我们一般情况下仅仅是需要动画结束时监听,那么我们就按照如下方式使用:

anim.addListener(new AnimatorListenerAdapter() {

	@Override
	public void onAnimationEnd(Animator animation) {
		// TODO Auto-generated method stub
		super.onAnimationEnd(animation);
	}

});

ValueAnimator

概念

ValueAnimator包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等。应用Property Animation有两个步聚:

  1. 计算属性值
  2. 根据属性值执行相应的动作,如改变对象的某一属性。

ValuAnimiator只完成了第一步工作,如果要完成第二步,需要实现ValueAnimator.onUpdateListener接口,这个接口只有一个函数onAnimationUpdate(),在这个函数中会传入ValueAnimator对象做为参数,通过这个ValueAnimator对象的getAnimatedValue()函数可以得到当前的属性值如:

protected void playAnim() {
		ValueAnimator animator = ValueAnimator.ofInt(0, 10);
		animator.setDuration(100);
		animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				Log.i("TAG", "AnimatedValue : " + animation.getAnimatedValue().toString());
			}
		});
		animator.start();
}

从上面的例子可以看到ValueAnimator类实现的是动画的插值因子的计算,大部分情况下我们使用ObjectAnimator就可以轻松实现很多种动画效果了,然后使用ObjectAnimator的View必须满足有getter和setter方法,若没有这些方法,使用ObjectAnimator的动画是无法实现的,我们只好考虑使用ObjectAnimator的父类ValueAnimator了,ValueAnimator实现动画不需要View含有getter和setter方法,它是通过计算动画的插值因子,我们根据这个插值自定义动画效果就可以了。

TypeEvaluator

TypeEvaluator是一个接口,通过实现该接口下的evaluate方法,可以实现我们自定义的各种复杂效果的动画:

ValueAnimator animator =ValueAnimator.ofObject(new TypeEvaluator<Number>() {

	@Override
	public Number evaluate(float fraction, Number startValue,Number endValue) {
		// TODO Auto-generated method stub
		return null;
	}
});

上面就是实现的TypeEvaluator接口,下面有个未实现的方法,这个回调函数中提供如下三个参数:

fraction:插值因子,取值范围0~1

startValue:动画的起始值

endValue:动画的结束值

我们可以根据这3个参数来编写计算自己需要的动画效果,样式很多样化的,不仅仅是ObjectAnimator里几种动画类型了。由此可以看出,ValueAnimator比ObjectAnimator更加灵活,方式更加繁多,我们自定义动画效果时,可以使用ValueAnimator实现TypeEvaluator接口来写自己的动画算法,实现比较复杂的动画。

关于属性动画的详细介绍,可以参考Google提供的官方文档,里面有非常详细的讲述:

http://developer.android.com/guide/topics/graphics/prop-animation.html

时间: 2024-10-15 21:53:57

Android属性动画简析的相关文章

Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/44171115 大家好,欢迎继续回到Android属性动画完全解析.在上一篇文章当中我们学习了属性动画的一些进阶技巧,包括ValueAnimator和ObjectAnimator的高级用法,那么除了这些之外,当然还有一些其它的高级技巧在等着我们学习,因此本篇文章就对整个属性动画完全解析系列收个尾,来学习一下剩下的非常重要的高级技巧. 另外,本篇文章中使用的代码是建立在上篇文章基础之

(转)Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法

目录(?)[-] Interpolator的用法 ViewPropertyAnimator的用法 转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/44171115 大家好,欢迎继续回到Android属性动画完全解析.在上一篇文章当中我们学习了属性动画的一些进阶技巧,包括ValueAnimator和ObjectAnimator的高级用法,那么除了这些之外,当然还有一些其它的高级技巧在等着我们学习,因此本篇文章就对整个属性动画完全解析

【转】android 属性动画之 ObjectAnimator

原文网址:http://blog.csdn.net/feiduclear_up/article/details/39255083 前面一篇博客讲解了 android 简单动画之 animtion,这里来讲解一下android 3.0之后添加的一些动画   animator 中的 ObjectAnimator . 属性动画概念: 所谓属性动画:改变一切能改变的对象的属性值,不同于补间动画:只能改变 alpha,scale,rotate,translate.听着有点抽象,举例子说明 补间动画能实现的

Android属性动画初步学习笔记

近期学习Android属性动画和VetcorDrawable实现属性动画,以此记录一下学习笔记. 首先是属性动画,小白没截过动态图,方三张静态图吧       效果是点击红色图片,7个选项以属性动画的方式弹出并旋转,最后成一个1/4圆弧排列,再次点击则收回到红色原点下. 布局文件很简单,就是一个RelativeLayout下八个ImageView: 1 <?xml version="1.0" encoding="utf-8"?> 2 <Linear

Android 属性动画(Property Animation) 完全解析 (上)

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38067475 1.概述 Android提供了几种动画类型:View Animation .Drawable Animation .Property Animation .View Animation相当简单,不过只能支持简单的缩放.平移.旋转.透明度基本的动画,且有一定的局限性.比如:你希望View有一个颜色的切换动画:你希望可以使用3D旋转动画:你希望当动画停止时,View的

Android属性动画完全解析

Android属性动画完全解析(上),初识属性动画的基本用法 Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法 Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法

Android属性动画之ValueAnimation

ValueAnimation是ObjectAnimation类的父类,经过前几天的介绍,相信大家对ObjectAnimation有了 一定的认识,今天就为大家最后介绍一下ValueAnimation,ValueAnimation谷歌提供了更好的过程控制,现在就以一个类计时的小动画为大家简单介绍一下: 应用的布局文件非常简单,只有一个Button按钮,就不再赘述了.下面重点介绍一下具体的实现: public void init() { button = (Button) findViewById(

Android 属性动画(Property Animation) 完全解析 (下)

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38092093 上一篇Android 属性动画(Property Animation) 完全解析 (上)已经基本展示了属性动画的核心用法: ObjectAnimator实现动画,ValueAnimator实现动画,AnimatorSet的使用等~ 当然了属性动画还有一部分的知识点,也能做出很不错的效果,将在本篇博客为您展示~ 1.如何使用xml文件来创建属性动画 大家肯定都清楚,

Android属性动画之ValueAnimator的介绍

之前两篇博客,介绍的是ObjectAnimator作用与某一个控件的某一个属性.但我们的ValueAnimator它本身并不会作用与任何一个属性,它本身也不会提供任何一种动画.它简单的来说,就是一个数值发生器,它可以产生你想要的各种数值.其实,在Android属性动画中,如何产生每一步具体实现动画效果,都是通过ValueAnimator计算出来的. 比如我们现在要实现一个从0~100的位移动画,ValueAnimator会根据动画持续的总时间产生一个0~1时间因子,有了这样一个时间因子.通过相应