Andorid动画——属性动画

上一篇主要记录了android补间动画与帧动画的使用:http://blog.csdn.net/yangzhaomuma/article/details/50530355

这里则是属性动画的使用和说明。

属性动画与补间动画、帧动画的写法区别

           在编写这两种动画的时候,你会发现他们在类的写法上是很相近的。初学者容易在这里混淆,这里做个简单说明:

            Animation 是针对View Animation(补间动画与帧动画)的动画实现,动画被应用时外观改变但视图的触发点不会发生变化,还是在原来定义的位置。

           Animator  是针对Property Animator(属性动画)的动画实现,动画被应用时对象属性产生变化,最终导致视图外观变化。

           这两个类派生出来的类,写法也遵循上面的原则,比如动画集合类。AnimatorSet 和 AnimationSet 都是动画集合,第一种是针对属性动画化,第二种是针对补间动画、

帧动画。

属性动画

以下是引用http://www.cnblogs.com/angeldevil/archive/2011/12/02/2271096.html中的说明,很全面,如下:

属性动画,这个是在Android 3.0中才引进的,它更改的是对象的实际属性,在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持

不变,比如无论你在对话中如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。而在Property Animator中,改变的是对象的实

际属性,如Button的缩放,Button的位置与大小属性值都改变了。而且Property Animator不止可以应用于View,还可以应用于任何对象。Property Animator只是表示一个值

在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。

在Property Animator中,可以对动画应用以下属性:

  • Duration:动画的持续时间
  • TimeInterpolation:属性值的计算方式,如先快后慢
  • TypeEvaluator:根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值
  • Repeat Count and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以此动画一直重复,或播放完时再反向播放
  • Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移
  • Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响

上面的说明基本说明了为什么我们要使用属性动画,而属性动画中,我们用到主要有以下的类型:Value Animator、Object Animator以及View Property Animator、Layout Animator。

Value Animator

将这个放在第一个介绍,是因为这个是属性动画的核心类。后续的几个方法基本都是继承或者有用到这个类的机制。

Value Animator,提供了多种方法改变属性值,来达到动画效果目的。

方法有四种:
(1)ValueAnimator.ofInt(1,2,3);  整型过度;
(2)ValueAnimator.ofFloat(0f,1f,200f);浮点型过度;
(3)ValueAnimator.ofObject(new FloatEvaluator(), 2f,1f,2f);对象类型过度;
(4)ValueAnimator.ofPropertyValuesHolder(PropertyValuesHolder);多属性动画同时工作;

这个类主要做的工作,就是改变值。如何使用这个类,我们先看一段代码:
ValueAnimator valueAnimator=null;
valueAnimator=ValueAnimator.ofFloat(0f,100f,50f);
		valueAnimator.setDuration(1000);
		valueAnimator.start();
大体如上,上面代码实现的就是值从0到100到50的过程。
为了能看到值的变换过程,我们可以给它添加一个监听函数,代码携程
ValueAnimator valueAnimator=null;
valueAnimator=ValueAnimator.ofFloat(0f,100f,50f);
valueAnimator.addUpdateListener(new updateListener());
		valueAnimator.setDuration(1000);
		valueAnimator.start();
监听类的实现如下:
class updateListener implements AnimatorUpdateListener
	{

		@Override
		public void onAnimationUpdate(ValueAnimator animation) {
			// TODO Auto-generated method stub
			Log.i(tag, animation.getAnimatedValue().toString());
			
		}
		
	}
这样,你就能看到值是如何变换的。但是这个还是没有涉及到我们的控件,这要怎么用呢???
必须的,我们要绑定一个控件,然后让控件实现属性值的变换,才算达到我们的动画效果。我们改写下方法如下:
ValueAnimator valueAnimator=null;
valueAnimator=ValueAnimator.ofFloat(0f,100f,50f);
		valueAnimator.setTarget(btnButton);//绑定控件
valueAnimator.addUpdateListener(new updateListener());
		valueAnimator.setDuration(1000);
		valueAnimator.start();
监听类实现改为:
class updateListener implements AnimatorUpdateListener
	{

		@Override
		public void onAnimationUpdate(ValueAnimator animation) {
			// TODO Auto-generated method stub
			Log.i(tag, animation.getAnimatedValue().toString());
			btnButton.setTranslationX(Float.parseFloat(animation.getAnimatedValue().toString()));//横向移动
			
		}
		
	}
对比代码不同的地方,很容易发现,我们只加了两行代码。setTarget+监听中的setTranslationX。这就很轻易的实现了控件横向从0移动到100,再移动到50的动画效果。当然,你还可以往这里添加很多其他的设置,比如TypeEvaluator,TimeInterpolation等,让效果更特别。

Object Animator

这个类,是继承上方Value Animator类。所以它的方法与Value Animator很类似。也是四种写法,方法名是一样的,但是参数是不同的。

它的方法,简单可以理解为Value Animator+setTarget方法,因为它的参数中是包含控件view的。使用它时,如果你想改变这个控件的属性X,需要这个控件中含有setX(),

getX()方法,否则不能使用。

我们用这个类的方法来实现补间动画的效果,代码如下:
public void simpleValue(int tag)
	{
		switch (tag) {
		case 1:
			objectAnimator=ObjectAnimator.ofFloat(btnButton, "alpha", 1,0,1);
			objectAnimator.setDuration(1000);
			objectAnimator.start();
			
		break;
		case 2:
				objectAnimator=ObjectAnimator.ofFloat(btnButton2, "rotation", 0f,360f);
				objectAnimator.setDuration(1000);
				objectAnimator.start();	
		break;
		case 3:
			
			objectAnimator=ObjectAnimator.ofObject(btnButton3, "translationX", new IntEvaluator(),0,300);
			objectAnimator.setDuration(1000);
			objectAnimator.start();	
			
		break;
		case 4:
			 PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);
			 PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0f, 1f);
		     PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f, 1f);
		        
			objectAnimator=ObjectAnimator.ofPropertyValuesHolder(btnButton4,pvhX,pvhY,pvhZ);
			objectAnimator.setDuration(1000);
			objectAnimator.start();	
		break;
		default:
			break;
		}
	}
实现起来,是很简单的。前两个实现看起来还是很简单的,只是简单的淡入淡出和旋转。但第三第四个方法,我们有新加了内容进去。

我们仔细分析下后面的两个方法:

(1)ObjectAnimator中的ofObject

看参数提示,第三个参数是TypeEvaluator,类型计算器。主要是用于计算属性变动之间,变动的系数。第三个方法中的IntEvaluator,是实现TypeEvaluator接口的一个类,表示变动过程为整数。

因为ofObject中,传入的参数是object型,也就是说,可以是各种类型,没有什么限制。有时候,我们就很有必要来自定义一个TypeEvaluator。

以下是一个简单的自定义例子:

/**
		     * 实现自定义TypeEvaluator,以简单的Float为例
		     */
			objectAnimator=ObjectAnimator.ofObject(btnButton3, "Y", new TypeEvaluator<Float>() {

				@Override
				public Float evaluate(float fraction, Float startValue,
						Float endValue) {
					// TODO Auto-generated method stub
					float fs= (float)startValue;
					float fe= (float)endValue;
					
					float result=fs+fraction*(fe-fs);
					return result;
				}
			},0f,500f);
			objectAnimator.setDuration(1000);
			objectAnimator.setInterpolator(new BounceInterpolator());
			objectAnimator.start();

这个方法中,我们用一个按钮的Y轴位置作为演示的对象。在我们的TypeEvaluator的实现中,fraction这个系数是系统计算后给出的。我们做的内容是,用这个系数乘以某一刻

结束位置的Y值减去起始位置的Y值,再加上起始位置的Y值,作为一个新值返回。

这样就实现了Y值,在界面上移动的轨迹。

上面方法中,有个Interpolator也是需要注意的,这个就是轨迹运动的方式了。比如先加速后减速、弹跳效果等。可以通过设定不同的这样的内插器来表现出来。

(2)ObjectAnimator中的PropertyValuesHolder

这个属性的解释如下:

* PropertyValuesHolder 属性值持有者  持有属性名、开始与结束值。

*  它的静态的一些of方法,创建 PropertyValuesHolder 对象。 

 *  ofInt、ofFloat、ofObject、ofKeyframe

它的大体用法,就如代码中写的,将多个动画效果轻易的混合。

/**
			 * PropertyValuesHolder 属性值持有者  持有属性名、开始与结束值。
			 *  它的静态的一些of方法,创建 PropertyValuesHolder 对象。 
			 *  ofInt、ofFloat、ofObject、ofKeyframe
			 */
			
			 PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);
			 PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0f, 1f);
		     PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f, 1f);
		        
			objectAnimator=ObjectAnimator.ofPropertyValuesHolder(btnButton4,pvhX,pvhY,pvhZ);
			objectAnimator.setDuration(1000);
			objectAnimator.start();


ViewPropertyAnimator

这是一种android 3.1版本后,出现的一种写法。更简便,更符合线性思维。

它的核心在于一个方法:animate()。所以的操作都是通过这个来实现的,我们可以在这过程中用连缀的写法。可以很简便的将动画简化为一行代码。

btnButton.animate().alpha(0f).setDuration(2000);

btnButton2.animate().x(300f).y(500f).setDuration(1000).setInterpolator(new BounceInterpolator());

btnButton3.animate().rotation(0f).rotation(360f).setDuration(1000);

btnButton4.animate().scaleX(0.5f).scaleY(1.5f).setDuration(1000);

这样的四行,就简单的实现了我们补间动画的效果。

这里有个特别的地方,在方法的最后,我们都没有加上start()方法。加上或者不加上,效果是一样的。内部会默认启动。



LayoutAnimation

布局动画。这是可以归在View Animation中的一种动画。不同于其他动画的地方在于这是对一组的控件进行动画效果的控制。

比如,一个linearlayout中的所有控件,做同一种动画效果。

布局动画的实现,我们也有两种方法实现:XML配置形式,代码形式。

写法分别如下:

(1)XML配置形式

定义一个layout_list.xml,如下:

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"

 android:delay="30%"  
 android:animationOrder="reverse"  
 android:animation="@anim/move" 
>
</layoutAnimation>

xml中我们设置了延迟参数,可以是百分比,也可以是具体的值,如30f等;

animationOrder用于控制该组控件动画的顺序,normal(正常,顺序)、reverse(反向)、random(随机);

最后,动画效果的配置,我们配置了move,这是一个自定义的xml。

move.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_interpolator">
    
    <translate
        android:fromXDelta="-100%"
        android:toXDelta="0"
        android:duration="500"
        ></translate>
</set>
效果:从左侧边框移入。

定义好以上的两个xml后,我们就可以在界面配置xml中加入以上的配置:

<LinearLayout 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
             android:layoutAnimation="@anim/layout_list"
            >
        <Button
         android:id="@+id/show1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="按钮1只显示..."
            ></Button>


        <Button
         android:id="@+id/show2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="按钮2只显示..."
            ></Button>
        </LinearLayout>

这样就实现了两个按钮的反向动画,从左侧边框移入。

(2)代码写法

代码的写法,我们也新加入一个动画效果作为演示,比如alpha,淡入淡出。

定义一个alpha.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:shareInterpolator="true">
    
     <alpha
       android:fromAlpha="1.0"
       android:toAlpha="0.0"
       android:duration="1000"/>
</set>

在代码中,我们获取LinearLayout的ID,并在代码中写如下语句:
public void setLayout()
	{
		Animation animation=AnimationUtils.loadAnimation(LayoutAnimationActivity.this, R.anim.alpha);
		LayoutAnimationController animationController=new LayoutAnimationController(animation);
		animationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
		animationController.setDelay(0.5f);
		//animationController.setInterpolator(new BounceInterpolator());
		layout.setLayoutAnimation(animationController);
	}
获取一个Animation的对象,在用这个对象作为参数,获取LayoutAnimationController的对象。再对这个对象进行必要的操作。最后绑定控件即可。

以上就是关于属性动画的所有介绍。

源码

源码中实现了文章中提到的补间动画、帧动画、属性动画、布局动画等。







猜你喜欢

转载自blog.csdn.net/yangzhaomuma/article/details/50545744