Android动画之属性动画

当我们看到别人的APP里面或者写的Demo里面的一些很牛逼得动画效果的时候,是否会有那么一种冲动我要看看它的源代码到底是怎么写的,为毛我就是写不出这样的动画效果呢,为毛我只能做哪些简单的平移,缩放,旋转,透明度改变的动画效果呢。呵呵,当你这么想的时候,证明你应该存在两种主要的问题:第一,就是你的确基础知识不过关,别人用到的东西,你根本就没有接触过,但是这些东西的确是API里面确实存在的东西。第二,就是你的经验不够,逻辑思维能力还有待提升。任何一个很酷很炫的动画效果,都应该是由一系列的动画效果合成的,这个时候就看你怎么安排和处理每一个小的动画效果最后合成你看到的动画效果。下面先介绍Android中的几种动画,最后会对属性动画(Property
Animation)做详细的介绍:

补间动画(Tween Animation):

       所谓的补间动画,个人理解其实就是定义了我们动画的起始点和终止点的状态,而动画的过程我们是不关心的,只需要达到我们想要的效果就行。

a. 渐变动画支持四种类型:平移(Translate)、旋转(Rotate)、缩放(Scale)、不透明度(Alpha)。

b. 只是显示的位置变动,View的实际位置未改变,表现为View移动到其他地方,点击事件仍在原处才能响应。

c. 组合使用步骤较复杂。

d. View Animation 也是指此动画。

帧动画(Frame Animation):

所谓的帧动画就是可以设置我们的动画的每一帧的效果,其实视频或者Gif的效果都是由许多张图片在很短的时间内播放,从而产生动画效果。

a. 用于生成连续的Gif效果图。

b.DrawableAnimation也是指此动画。

属性动画(Property Animation)

a. 支持对所有View能更新的属性的动画(需要属性的setXxx()和getXxx())。

b. 更改的是View实际的属性,所以不会影响其在动画执行后所在位置的正常使用。

c. Android3.0 (API11)及以后出现的功能,3.0之前的版本可使用github第三方开源库nineoldandroids.jar进行支持。

属性动画的相关的API:

ValueAnimator :值动画执行类,常配合AnimatorUpdateListener使用。

ObjectAnimator :对象动画执行类。

PropertyValuesHolder: 属性存储器,为两个执行类提供更新多个属性的功能。

AnimatorListener :动画执行监听,在动画开始、重复、结束、取消时进行回调。

Keyframe :为PropertyValuesHolder提供多个关键帧的操作值。

AnimatorSet :一组动画的执行集合类:设置执行的先后顺序,时间等。

TimeInterpolator :时间插值,用于控制动画执行过程。

AnimatorUpdateListener:动画更新监听。

TypeEvaluator :类型估值,用于设置复杂的动画操作属性的值。

ValueAnimator和ObjectAnimator是属性动画里面经常使用的对象类,ObjectAnimator是ValueAnimator的子类,看看ValueAnimator的类结构:

在ValueAnimator类中经常用到的几个方法:

public static ValueAnimator ofInt(int... values){   }      //设置类型为int的属性的值,例如X,Y坐标,可变长的数组值,设置属性值在之间变化

public static ValueAnimator ofFloat(float... values) { }  //设置类型为float的属性的值,例如alpha,translationX,translationY等等属性

public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values)     //当我们对某一个控件的多个属性实行动画的时候  可以用PropertyValuesHolder保存每一个属性的动画效果,最后调用这个方法组合起来,参数也是一个可变长的。

public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values)    //设置某个对象的动画  在后面做详细介绍

1.ObjectAnimator

下面先讲讲ObjectAnimator的用法(因为实际中这个用的更多。PS:完全个人感觉)

ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 0f,200f);
oa.setDuration(1000);
oa.start();  

上面代码实现的是改变控件iv的translationX的值,从0到200,0f表示从0开始使X坐标平移,这个值可以自己设置,当我们是指的值加入设定为100f的时候,给我们的感觉就是控件iv首先跳到X坐标为100f处(这个100指的是相对于控件坐标的左上角为原点)

                 
           

左图为0f,200f时的效果,右图为100f,200f的效果,明显感觉右侧的动画突然跳跃了一段距离。

其他各种属性的值,我们可以去对应控件的类或者顶级View的源码里面查看,不再一一赘述了。

ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 0f,100f);
oa.setDuration(2000);
//设置重复次数  次数为-1的时候重复模式INFINITE才有作用意思是一直重复执行
oa.setRepeatCount(-1);
//设置重复的模式   INFINITE 无限重复执行  RESTART 从开始重复执行  REVERSE 反转重复执行(类似反着执行一次)
oa.setRepeatMode(ObjectAnimator.REVERSE);
//动画在延迟1000毫秒之后开始
oa.setStartDelay(1000);
//开始动画
oa.start();  

上面的动画效果是重复执行,注释很清楚了。

2.PropertyValueHolder

他可以设置多个动画同时作用于同一个空间,有点类似于补间动画的动画集合AnimationSet

//属性存储器
PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 0,100,200,300);
//缩放动画,X Y轴缩放比例从原始比例,缩小到最小,再放大到原始比例1f 再又缩放到最小  最后放大到最大
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f,0f,1f,0f,1f);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f,0f,1f,0f,1f);
//同时执行三个动画
ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(iv,pvh1,pvh2,pvh3);
oa.setDuration(1000);
oa.start();  

最后运行的动画效果 可能由于浏览器的原因,没有缩放到最小,后面会将源码留下,大家可以去模拟器上看看效果。

AnimatorSet可以实现同样的类似于PropertyValueHolder的功能 但是AnimatorSet功能更强大,它可以设置某一个动画在另外一个动画前面或者后面执行,还可以设置某几个动画同时执行。

<pre name="code" class="java">AnimatorSet set = new AnimatorSet();
		//透明度
		ObjectAnimator anim1 = ObjectAnimator.ofFloat(iv, "alpha", 0f,1f);
		anim1.setDuration(4000);
		//横向平移
		ObjectAnimator anim2 = ObjectAnimator.ofFloat(iv, "translationX", 0f,100f);
		anim2.setDuration(3000);
		//纵向平移
		ObjectAnimator anim3 = ObjectAnimator.ofFloat(iv, "translationY", 0f,100f);
		anim3.setDuration(3000);
		//旋转
		ObjectAnimator anim4 = ObjectAnimator.ofFloat(iv, "rotation", 0f,360f);
		anim4.setDuration(500);

		//制定动画执行的顺序
		//anim1 在 anim2 之前执行
		set.play(anim1).before(anim2);
		//anim2 anim3 同时执行
		set.play(anim2).with(anim3);
		//anim4 在 anim3之后执行
		set.play(anim4).after(anim3);
		set.start();

执行效果如下图

AnimatorSet里面有几个控制动画执行先后顺序的方法

  • after(Animator anim)   将现有动画插入到传入的动画之后执行
  • after(long delay)   将现有动画延迟指定毫秒后执行
  • before(Animator anim)   将现有动画插入到传入的动画之前执行
  • with(Animator anim)   将现有动画和传入的动画同时执行

3.关键帧KeyFrame

意思就是设置动画的某一帧(关键帧)的效果,先看代码和效果图,在根据代码和效果图仔细讲解

//关键帧
//Keyframe 定义动画在特定的时间点上特定的状态
//第一个0,动画的执行进度,第二个0,初始的状态(0度)
//  Keyframe kf0 = Keyframe.ofFloat(0f,0f);
//动画执行到30%时,应该旋转了360度
//Keyframe kf1 = Keyframe.ofFloat(0.2f,360f);
//  Keyframe kf1 = Keyframe.ofFloat(0.2f,1f);
//动画执行到100%,重新旋转到0度
//  Keyframe kf2 = Keyframe.ofFloat(1f,0f);
Keyframe kf0=Keyframe.ofFloat(0f,0f);
Keyframe kf1=Keyframe.ofFloat(0.1f,100f);
Keyframe kf2=Keyframe.ofFloat(1f,300f);  

//区别:ObjectAnimator.ofFloat(iv, "rotation", 0f,360f,0f);
//将关键帧打包
PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationX", kf0,kf1,kf2);
//  PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("alpha", kf0,kf1,kf2);
//创建属性动画对象
ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(iv,holder);
oa.setDuration(2000);
oa.start();  

代码的第10定义了关键帧kf0,调用了Keyframe.ofFloat(float fraction , float value) ,第一个参数代表的是动画执行的进度,在此kf0的fraction=0f,就是动画开始执行的时候,属性类型为Float的值为value

代码的第11行fraction=0.1f表示动画执行到10%的时候 属性值(本例中为translationX的值)为100f,同理kf2中动画执行完成之后translationX的值为300f,整个过程中fraction的值为0~1,不能超过1。

代码16行将关键帧打包到PropertyValueHolder中,并且将所有的关键帧的效果作用在属性"translationX"上。最后执行动画。本例的动画执行效果就是控件iv 在沿X平移的时候0-100px内移动的快一些(换算成时间就是在0.1s内平移了100px)后面的200px在0.9s内执行完成

4.事件监听

	ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "alpha", 1f,0f);
	oa.setDuration(1000);
	oa.addListener(new Animator.AnimatorListener() {

		@Override
		public void onAnimationStart(Animator animation) {
			//动画开始时调用
		}

		@Override
		public void onAnimationRepeat(Animator animation) {
			//动画重复时调用
		}

		@Override
		public void onAnimationEnd(Animator animation) {
			////动画结束时调用
			//移除按钮
			ViewGroup parent = (ViewGroup) btn.getParent();
			if (parent != null) {
				parent.removeView(btn);
			}
		}

		@Override
		public void onAnimationCancel(Animator animation) {
			//动画取消时调用
		}
	});
	oa.start();

代码中为ObjectAnimator设置了事件监听AnimatorListener,可以重写其中的四个方法onAnimationStart表示动画刚刚开始执行时候的回调,onAnimationRepeat动画重复执行的时候回调,onAnimationEnd动画执行完毕的时候的回调,大部分应用程序都会复写这个方法来执行相关的操作,onAnimationCancel动画取消的时候回调。

如果在程序中我们需要监听动画的完成或者执行状态但是不想回调或者复写AnimatorListener的方法的时候,可以用AnimatorListener的子类AnimatorListenerAdapter,选择你需要重写的方法,而不必重写所有的方法。

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

5.插值器Interpolator

对于不同的插值器有不同的动画效果,可以调用ObjectAnimator的setInterpolator()方法设置自己向想要的插值器。TimeInterpolator时间插值器,是以上所有插值器的父接口,我们可以写自己的插值器的实现,重写其getInterpolation方法,也可以用上面图片所提到的几种插值器,这都是谷歌帮我们写好的。

AccelerateInterpolator:加速差值,意思就是动画执行的速度越来越快。

AniticipateInterpolator:动画执行的效果是控件会从动画开始执行的地方倒退一段距离之后再执行,和OvershootInterpolator相反,OvershootInterpolator是在动画执行完成之后继续执行一段距离,有点类似跳出当前控件所在的父容器之外的感觉

LinearInterpolator:线性插值器,就是类似匀速运动的效果

DecelerateInterpolator:减速插值器,开始动画执行快,后面没执行慢

BounceInterpolator:动画执行的效果类似乒乓球掉在地上的效果,落地之后会反弹,知道最后完全停止。

CycleInterpolator:字面意思 ,循环插值器,可以使动画循环执行多次,类似repeate效果,控制translationX属性可以做出控件的抖动效果

当然还可以有这几种插值器的组合效果。

6 ValueAnimator

正如前面所说,ValueAnimator就是值动画执行类,常配合AnimatorUpdateListener使用。他和ObjectAnimator的区别是,ObjectAnimator是ValueAnimator的子类,在调用ofFloat,ofInt....创建ValueAnimator的时候我们不需要也不能像ObjectAnimator
oa = ObjectAnimator.ofFloat(iv, "translationY", 0,300); 这样为动画指定相应的属性(translationY),俗套的说,就是计算你知道你要改变的属性输translationY但是你也不能再创建的时候指定它,你只能指定属性的取值范围,例如ValueAnimator va = ValueAnimator.ofFloat(0f,200f); 你只知道0f~200f但是从代码字面意思你不知道到底是什么属性0f~200f,这时候就需要配合AnimatorUpdateListener来使用了,在AnimatorUpdateListener的onAnimationUpdate中写我们的动画的具体执行逻辑。

ValueAnimator va = ValueAnimator.ofFloat(0f,200f);
va.setDuration(2000);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
	@Override
	public void onAnimationUpdate(ValueAnimator animation) {
		float v = Float.parseFloat(animation.getAnimatedValue().toString());
		//如果要使动画同时适配API11以下的版本 就得使用开源jar包nineoldandroids.jar进行统一适配
		//操作方法就变成了ViewHelper.setTranslationX(iv, v);
		iv.setTranslationX(v);
		//优点:可以同时在回掉方法中,更新多个控件的属性
		//使用ObjectAnimator还是ValueAnimator取决于是否在一个动画中更新多个控件的属性
		//ViewHelper.setTranslationY(btn, v);
	}
});
va.start();

例子很简单,但是能够说明ValueAnimator的简单使用方法,我们可以在回调方法onAnimationUpdate方法中处理多个控件(其他非动画执行的控件的状态),当然ValueAnimator还可以配合AnimatorListener使用监听动画执行的开始,结束,重复,取消等操作,也可以使用AnimatorListenerAdapter只监听其中的动画执行的某一个状态。

7 TypeEvaluator

类型估值,用于设置复杂的动画操作属性的值,它是一个接口,有3个实现类,分别为IntEvaluator,FloatEvaluator,ArgbEvaluator,从字面意思可以看出他们的意思。和上面的ofFloat,ofInt有异曲同工之妙。这三个实现类都实现了TypeEvaluator中的抽象方法public T evaluate(float fraction, T startValue,
T endValue);   其中float fraction表示动画执行的进度,T startValue泛型startValue表示动画开始执行的位置或者状态,endValue代表动画执行结束的位置或者状态  ,用泛型T表示 说明开发者可以根据自己的需要,定义自己的TypeEvalotor,例如Integer,Float,Point,PointF...等等。下面说说他们的简单用法。

FloatEvaluator evaluator=new FloatEvaluator();
ValueAnimator valueAnimator = ValueAnimator.ofObject(evaluator,0,200);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {

	@Override
	public void onAnimationUpdate(ValueAnimator animation) {
		float x=Float.parseFloat(animation.getAnimatedValue().toString());
		iv.setX(x);
	}
});
valueAnimator.setDuration(3000);
valueAnimator.start();

上面动画的意思是使控件IV的X坐标从0-200改变,类似做直线运动,效果图就免了,很简单。

下面来说说TypeEvaluator的用法,先上代码和效果。

 final PointF point = new PointF();
		TypeEvaluator<PointF> typeEvaluator = new TypeEvaluator<PointF>() {
			//
			@Override
			public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
				//fraction 就相当于进度0->1
			//	point.x=(endValue.x-startValue.x)*fraction;
			//	point.y=(endValue.y-startValue.y)*fraction;
				point.x=(endValue.x-startValue.x)*fraction;
				point.y=600+200*(float) Math.sin(point.x/65);
				return point;
			}
		};
		ValueAnimator valueAnimator = ValueAnimator.ofObject(typeEvaluator, new PointF(0,600),new PointF((float)(260*Math.PI),600));
		valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				//getAnimatedValue方法返回的值,由evaluate计算得到的
				PointF point = (PointF) animation.getAnimatedValue();
			//	ViewHelper.setX(iv, point.x);
			//	ViewHelper.setY(iv, point.y);
				iv.setX(point.x);
				iv.setY(point.y);
			}
		});
		valueAnimator.setDuration(3000);
		valueAnimator.start();

上面的代码使用TypeEvaluator实现了控件IV沿着我们设置的正弦曲线运动,正弦函数为y=600+200*sin(x/65);

代码第1行首先定义一个点PointF 应为里面的坐标为float类型,所以使用PointF

代码第2-13行定义了一个TypeEvalutor并重写了evaluate方法 泛型T代表PointF

代码第9行定义了点的x坐标为point.x=(endValue.x-startValue.x)*fraction;

代码第10行定义了y坐标,我们根据正弦函数的函数方程式写出point.y=600+200*(float) Math.sin(point.x/65); 由于手机屏幕的坐标的水平向右为X正方形,垂直向下为Y轴正方形,数字600  ,200 ,主要是为了增加Y轴的幅度,使动画效果更加明显,65主要是为了扩大X轴方向的距离。

代码第14行创建ValueAnimator对象并调用ofObject方法,将TypeEvaluator,startValue,endValue传递给它。

代码15行,添加动画监听,这正应证了前面说的ValueAnimator通常和ValueAnimator.AnimatorUpdateListener配对使用,在他的回调方法onAnimationUpdate里面控制空间IV的x和y坐标 最后启动动画就得到上面的效果。

文章可能写的不太全面,好多该详细讲解的地方,可能没有讲解到,本文只是讲解了属性动画中常用的一些API,想要写出非常炫酷的动画效果,还是需要开篇所说的逻辑思维能力。希望本文能给大家带来些帮助,谢谢。代码传送门源码

时间: 2024-10-13 02:57:51

Android动画之属性动画的相关文章

Android开发实战之补间动画和属性动画

说起动画,其实一点也不陌生,在使用一款app的时候为了优化用户体验,多多少少的,都会加入动画. 安卓中的动画,分为两大类:补间动画和属性动画.本篇博文会详细介绍总结这两大动画,希望本篇博文对你的学习和生活有所帮助. **补间动画** 补间动画分为四类:平移动画,旋转动画,缩放动画和渐变动画.这几类动画用法都差不多,只是对象参数不同这里我统一展示出来.以下是效果图: 实现代码很简单: btn1.setOnClickListener(new View.OnClickListener() { @Ove

Android动画:模拟开关按钮点击打开动画(属性动画之平移动画)

在Android里面,一些炫酷的动画确实是很吸引人的地方,让然看了就赏心悦目,一个好看的动画可能会提高用户对软件的使用率.另外说到动画,在Android里面支持两种动画:补间动画和属性动画,至于这两种动画的区别这里不再介绍,希望开发者都能在使用的过程中体会两者的不同. 本文使用属性动画完成,说到属性动画,肯定要提到 JakeWharton大神写的NineOldAndroids动画库,如果你的app需要在android3.0以下使用属性动画,那么这个库就很有作用了,如果只需要在高版本使用,那么直接

Android动画学习(缓动动画与属性动画的区别)

前言: 在 Android动画学习(概述)中,如果你看过这篇帖子,你应该会对缓动动画和属性动画之间的区别产生疑问,因为在它们的应用中,你会感觉这两种动画有着一些相似的地方,为此,我打算把这两种动画之间的区别做一下说明 区别: 在这里先附上官方文档对于这两种动画的区别说明(我所说的缓动动画对应在下文中的英文为:View Animation,属性动画对应在下文中的英文为:Property Animation): How Property Animation Differs from View Ani

Android研究之属性动画(Property Animation)完全解析详解下

 上一篇Android研究之属性动画(Property Animation)完全解析详解上已经基本展示了属性动画的核心用法: ObjectAnimator实现动画,ValueAnimator实现动画,AnimatorSet的使用等~ 当然了属性动画还有一部分的知识点,也能做出很不错的效果,将在本篇博客为您展示~ 1.如何使用xml文件来创建属性动画 大家肯定都清楚,View Animator .Drawable Animator都可以在anim文件夹下创建动画,然后在程序中使用,甚至在The

Android笔记之属性动画

前言.动画分类 如下图所示,Android的动画主要分为三种: 下面首先说说 属性动画 所谓属性动画-- 就是指对象的属性值发生了变化,如控件位置和透明度等. 举例,现在要实现一个按键先下移,再右移的动画. (1)编写动画xml 由于新建android工程的时候,在res下面并没有专门放置动画xml的文件夹,因此,我们新建一个animator名称的文件夹.建议不要起别的名字,因为ADT对res的文件夹命名有检索功能,如起animator这个名字的时候,ADT就能根据名称识别出这个是动画xml文件

安卓中的动画之属性动画(1)

属性动画(Property Aniamtion)是在谷歌新推出的一种动画. 1.什么是属性动画? 属性动画,顾名思义,就是操作属性的动画.在这里可能有人要问什么是操作的属性?想想以前我们学习的动画--变换动画,可以更改动画显示的各种形态,看上去非常炫酷:布局动画,可以更改activity跳转你的动画:帧动画,就是flash动画一样.我们在使用这些动画时,特别是变换动画时,有没有想过,假如一个imageview有一个监听事件,而我们使用变换动画更换了imageview的位置时,此时我们想要实现这个

Android学习之 属性动画&lt;Property Animation&gt;

property 动画系统是相当健壮的框架,它几乎可以动画显示任何对象. 你可以定义一个动画来定时改变任何对象的属性值,不论该对象是否在屏幕上显示. property 动画将以一定的时间间隔修改属性值(对象中的字段值). 要实现动画显示,你须指定对象的相应属性(比如对象的屏幕位置),以及动画时长.动画时间间隔. property 动画系统能让你设定以下动画要素: 1.持续时间:指定动画的持续显示时间.默认的时长是300毫秒. 2.插值因子:指定属性值的变化方式,表示为关于动画已显示时间的函数.

Android(java)学习笔记264:Android下的属性动画高级用法(Property Animation)

1. 大家好,在上一篇文章当中,我们学习了Android属性动画的基本用法,当然也是最常用的一些用法,这些用法足以覆盖我们平时大多情况下的动画需求了.但是,正如上篇文章当中所说到的,属性动画对补间动画进行了很大幅度的改进,之前补间动画可以做到的属性动画也能做到,补间动画做不到的现在属性动画也可以做到了.因此,今天我们就来学习一下属性动画的高级用法,看看如何实现一些补间动画所无法实现的功能. 2. ValueAnimator的高级用法: 在上篇文章中介绍补间动画缺点的时候有提到过,补间动画是只能对

Android之Fragment,帧动画,补件动画,属性动画

Fragment: 在安卓手机越来越大的情况下,一个屏幕显示只显示一个内容,会显得空旷,布局不够好看,屏幕利用的也不够充分.通常在平板中会出现这种情况,但是由于现在的手机屏幕越来越大,所以在3.0之后引入了Fragment.也可以使用支持类库,来向下兼容低版本.它的生命周期方法和activity一样 使用Fragment可以让我们更加充分地利用手机的屏幕空间,他可以在一个activity中有多个Fragment,多个Fragment可以显示不同的内容. 我们通过简单的demo来了解什么是Frag