上一篇主要记录了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>
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的对象。再对这个对象进行必要的操作。最后绑定控件即可。
以上就是关于属性动画的所有介绍。