Android ValueAnimator详解
Android Property Animation
属性动画,这个是在Android 3.0中才引进的,以前学WPF时里面的动画机制好像就是这个,它更改的是对象的实际属性,在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变。比如无论你在对话中如何缩放Button的大小,Button的有效点击区域是没有应用动画时的区域,其位置与大小都不变。而在Property Animation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。而且Property Animation不止可以应用View,还
可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全由自己决定的。
在Property Animation中,可以对动画应用以下属性:
1)Duration:动画的持续时间
2)TimeInterpolation:属性的计算方式,如先快后慢
3)TypeEvaluator:根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值
4)Repeat Country and behavoir:重复次数与方式,如播放3次,5次,无限循环,可以此动画一直重复,或者播放完时再反向播放。
5) Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同的动画设置不同开始偏移
6)Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终的刷新时间,还受到系统进程调度与硬件的影响。
3.1 Property Animation的工作方式
对于下图的动画,这个对象的X坐标在40ms内从0移动到40px,按照默认的10ms刷新一次,这个对象会移动四次,每次移动40/4 = 10 pixel
其一般使用方法如下:
AnimationSet animationSet =newAnimationSet(true);
/**
* 前两个参数定义旋转的起始和结束的度数,后两个参数定义圆心的位置
*/
RotateAnimation rotateAnimation =newRotateAnimation(0, 360,
Animation.RELATIVE_TO_PARENT, 1f,
Animation.RELATIVE_TO_PARENT, 0f);
rotateAnimation.setDuration(5000);
animationSet.addAnimation(rotateAnimation);
imageView.startAnimation(animationSet);
另外通过AnimatorSet对象来实现多个Animator的共同实现。
AnimationSet提供了一个把多个动画组合成一个组合的机制,并可设置组中动画的时序关系,如同时播放,顺序播放等。
以下例子同时应用5个动画:
播放anim1;
同时播放anim2,anim3,anim4;
播放anim5。
1
2
3
4
5
6
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();
当前有个APIdemo:
首先实现的ShapeHolder类:
-----------------------------------------------------------------------------
package com.example.animate;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.drawable.ShapeDrawable;
public class ShapeHolder {
private float x = 0, y = 0;
private ShapeDrawable shape;
private int color;
private RadialGradient gradient;
private float alpha = 1f;
private Paint paint;
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public ShapeDrawable getShape() {
return shape;
}
public void setShape(ShapeDrawable shape) {
this.shape = shape;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public RadialGradient getGradient() {
return gradient;
}
public void setGradient(RadialGradient gradient) {
this.gradient = gradient;
}
public float getAlpha() {
return alpha;
}
public void setAlpha(float alpha) {
this.alpha = alpha;
}
public Paint getPaint() {
return paint;
}
public void setPaint(Paint paint) {
this.paint = paint;
}
}
自定义的类:
-------------------------------------------------------
package com.example.animate;
import java.util.ArrayList;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
public class MyView extends View{
public final ArrayList balls = new ArrayList();
ValueAnimator bounceAnim=null;
ShapeHolder ball=null;
/**
* @param context
*/
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
ball =createBall(25,25);
setWillNotDraw(false); //这一行必须要写进去
}
private void createAnimation(){
if(null == bounceAnim){
//ValueAnimator创建的对象是从一个点运动到另外一个点
bounceAnim = ValueAnimator.ofFloat(ball.getY(),this.getHeight()-50);
bounceAnim.setDuration(1500);
bounceAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
float value = (Float) animation.getAnimatedValue();
ball.setY( value );
invalidate();
}
});
bounceAnim.setInterpolator(new AccelerateInterpolator( 2f ));
}
}
public void startAnimation(){
createAnimation();
bounceAnim.start();
}
public void reverseAnimation(){
createAnimation();
bounceAnim.reverse();
}
public void seek(long seekTime){
createAnimation();
bounceAnim.setCurrentPlayTime(seekTime);
}
private ShapeHolder createBall(int x,int y){
// OValShape为创建一个椭圆,
OvalShape circle = new OvalShape();
circle.resize(50f, 50f);
ShapeDrawable drawable=new ShapeDrawable(circle);
ShapeHolder shapeHolder = new ShapeHolder();
//设置当前的ShapeHolder的颜色
shapeHolder.setShape(drawable);
shapeHolder.setX(x-25f);
shapeHolder.setY(y-25f);
//提供想一个的颜色
int red = (int)(Math.random()*255);
int green = (int)(Math.random()*255);
int blue = (int)(Math.random()*255);
int color = 0xFF000000 |red<<16|green<<8|blue;
Paint paint=drawable.getPaint();
int darkColor = 0xff000000 | red/4 <<16|green/4<<8|blue/4;
RadialGradient gradient = new RadialGradient(37.5f,12.5f,50f,
color,darkColor,Shader.TileMode.CLAMP);
paint.setShader(gradient);
shapeHolder.setPaint(paint);
return shapeHolder;
}
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.save();
canvas.translate(ball.getX(), ball.getY());
ball.getShape().draw(canvas);
canvas.restore();
}
}
最终实现当前主程序代码:
---------------------------------------------------------------------------
package com.example.animate; import android.animation.ValueAnimator; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.LinearLayout; public class MainActivity extends Activity implements OnClickListener{ private Button mButtonTest,mButtonAction; LinearLayout container=null; MyView myView=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); container = (LinearLayout)findViewById(R.id.container); myView = new MyView(this); container.addView(myView); mButtonTest = (Button)findViewById(R.id.startButton); mButtonTest.setOnClickListener(this); mButtonAction = (Button)findViewById(R.id.reverseButton); mButtonAction.setOnClickListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } /* (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ @Override public void onClick(View v) { // TODO Auto-generated method stub if(v.getId() == R.id.startButton){ myView.startAnimation(); }else{ myView.reverseAnimation(); } } }