在介绍本文动画效果实现之前,先来介绍属性动画相关的几个知识点。
在Android3.0之前,系统提供了两种动画效果实现方式,帧动画frame-by-frame animation和补间动画tweened animation。帧动画就是类似电影播放一样,将整部影片拆分成一片片的然后连贯起来播放。补间动画则可以实现对view的缩放、平移、旋转等操作。在3.0之后,出现了一种新的动画模式称为属性动画property animation。
属性动画产生的原因
属性动画的出现不是用来替代补间动画的,而是用来解决补间动画所不能够完成的事件的。如果我们的需求超出了操控view的旋转、缩放、平移等操作范围,那么我们就需选择属性动画去实现了。那么属性动画可以做到哪些补间动画做不到的事情呢?下面列举几点,当然属性动画的功能很强大,不仅限于我列举的几点。
ValueAnimator与ObjectAnimator
ObjectAnimator是属性动画中最总要的执行类,ObjectAnimator可以操作某个对象的属性值,但是这个属性值必须要有get和set方法,同时也可以设置view的执行线路,通过插值器来控制。
举个简单的例子:
ObjectAnimator
.ofFloat(view, "rotationY", 0.0F, 360.0F)
.setDuration(500)
.start();
其可操作的属性有x/y;scaleX/scaleY;rotationX/ rotationY;transitionX/ transitionY等。
上面的例子是修改view的单个属性值,同样也可以同时修改多个属性,下面介绍两种
PropertyValuesHolder属性值持有者
PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1);PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1);ObjectAnimator.ofPropertyValuesHolder( this, pvhLeft, pvhTop).
提供一个不存在的属性值
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "long", 1.0F, 0.0F).setDuration(500);
anim.start();
anim.UpdateListener(new AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float cVal = (Float) AnimatedValue();view.setAlpha(cVal);view.setScaleX(cVal);view.setScaleY(cVal);}
});
上面提到的都是修改对象已有的setter和getter方法的属性值。那么如果对象没有为某个属性提供提供setter和getter方法呢,我们也可以做到修改这些属性值,下面提供两种实现方式:
通过自己写一个包装类来实现。然后为该属性提供setter和getter方法。
class ViewWrapper{private View mView;public int getWidth(){LayoutParams().width;}
}
ValueAnimator包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等。
属性动画的应用有两个步骤:
1、计算属性的值。2、根据属性值执行相应的动作。
ValueAnimator只是完成了第一步骤,而要完成第二步还要借助于UpdateListener接口,在此方法中可以通过ValueAnimator对象的getAnimatedValue()函数可以得到当前的属性值。
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.addUpdateListener(new AnimatorUpdateListener () {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {Log.i("update", ((AnimatedValue()).toString());// 此处可以根据getAnimatedValue获取到的属性值改变view相关的属性从而执行某些动作}
});
animation.setInterpolator(new CycleInterpolator(3));
animation.start();
Time Interpolator插值器与TypeEvaluator估值器
Time interplator:定义了属性值变化的方式,如线性均匀改变,开始慢然后逐渐快等。在Property Animation中是TimeInterplator,在View Animation中是Interplator,这两个是一样的,在3.0之前只有Interplator,3.0之后实现代码转移至了TimeInterplator。Interplator继承自TimeInterplator,内部没有任何其他代码。
TypeEvaluator:根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值,android提供了以下几个evalutor:
当然我们也可以自己定义估值器,如下:
public class FloatEvaluator implements TypeEvaluator {public Object evaluate(float fraction, Object startValue, Object endValue) {float startFloat = ((Number) startValue).floatValue();return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);}
}
实例
接下来我们要实现的就是如下的 效果图:
在本例的实现中我们的重点也是在ValueAnimator和ObjectAnimator中读者可以结合上述知识内容来消化本例的动画技术。附上代码:
ample.custom.animation;import java.util.ArrayList;ample.custom.R;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
t.Context;
aphics.Canvas;
aphics.Paint;
aphics.RadialGradient;
aphics.Shader;
aphics.drawable.ShapeDrawable;
aphics.drawable.shapes.OvalShape;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.LinearLayout;public class BouncingBalls extends Activity {@Overridepublic void onCreate(Bundle savedInstanceState) {Create(savedInstanceState);setContentView(R.layout.bouncing_balls);LinearLayout container = (LinearLayout) findViewById(ainer);container.addView(new MyAnimationView(this));}public class MyAnimationView extends View {private static final int RED = 0xffFF8080;private static final int BLUE = 0xff8080FF;public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>();AnimatorSet animation = null;public MyAnimationView(Context context) {super(context);ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);colorAnim.setDuration(3000);colorAnim.setEvaluator(new ArgbEvaluator());colorAnim.setRepeatCount(ValueAnimator.INFINITE);colorAnim.setRepeatMode(ValueAnimator.REVERSE);colorAnim.start();}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (Action() != MotionEvent.ACTION_DOWN &&Action() != MotionEvent.ACTION_MOVE) {return false;}// 初始化一个跳跳球ShapeHolder newBall = X(), Y());float startY = Y();float endY = getHeight() - 50;float h = (float)getHeight();float eventY = Y();int duration = (int)(500 * ((h - eventY)/h));// 操作newBall的Y属性值ValueAnimator bounceAnim = ObjectAnimator.ofFloat(newBall, "y", startY, endY);bounceAnim.setDuration(duration);bounceAnim.setInterpolator(new AccelerateInterpolator());ValueAnimator squashAnim1 = ObjectAnimator.ofFloat(newBall, "x", X(),X() - 25f);squashAnim1.setDuration(duration/4);squashAnim1.setRepeatCount(1);squashAnim1.setRepeatMode(ValueAnimator.REVERSE);squashAnim1.setInterpolator(new DecelerateInterpolator());ValueAnimator squashAnim2 = ObjectAnimator.ofFloat(newBall, "width", Width(),Width() + 50);squashAnim2.setDuration(duration/4);squashAnim2.setRepeatCount(1);squashAnim2.setRepeatMode(ValueAnimator.REVERSE);squashAnim2.setInterpolator(new DecelerateInterpolator());ValueAnimator stretchAnim1 = ObjectAnimator.ofFloat(newBall, "y", endY, endY + 25f);stretchAnim1.setDuration(duration/4);stretchAnim1.setRepeatCount(1);stretchAnim1.setInterpolator(new DecelerateInterpolator());stretchAnim1.setRepeatMode(ValueAnimator.REVERSE);ValueAnimator stretchAnim2 = ObjectAnimator.ofFloat(newBall, "height",Height(), Height() - 25);stretchAnim2.setDuration(duration/4);stretchAnim2.setRepeatCount(1);stretchAnim2.setInterpolator(new DecelerateInterpolator());stretchAnim2.setRepeatMode(ValueAnimator.REVERSE);ValueAnimator bounceBackAnim = ObjectAnimator.ofFloat(newBall, "y", endY, startY);bounceBackAnim.setDuration(duration);bounceBackAnim.setInterpolator(new DecelerateInterpolator());AnimatorSet bouncer = new AnimatorSet();bouncer.play(bounceAnim).before(squashAnim1);bouncer.play(squashAnim1).with(squashAnim2);bouncer.play(squashAnim1).with(stretchAnim1);bouncer.play(squashAnim1).with(stretchAnim2);bouncer.play(bounceBackAnim).after(stretchAnim2);ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);fadeAnim.setDuration(250);fadeAnim.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {ve(((ObjectAnimator)animation).getTarget());}});AnimatorSet animatorSet = new AnimatorSet();animatorSet.play(bouncer).before(fadeAnim);animatorSet.start();return true;}private ShapeHolder initBouncingBall(float x, float y) {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;int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4;// 实例化一个圆形OvalShape circle = new OvalShape();size(50f, 50f);// 设置画笔的形状ShapeDrawable drawable = new ShapeDrawable(circle);Paint paint = Paint(); // 第一个,第二个参数表示渐变圆中心坐标,半径,圆心颜色,圆边缘颜色,渲染器平铺模式RadialGradient gradient = new RadialGradient(37.5f, 12.5f, 50f, color, darkColor, Shader.TileMode.CLAMP);// 给画笔设置著色器paint.setShader(gradient);ShapeHolder shapeHolder = new ShapeHolder(drawable);shapeHolder.setX(x - 25f);shapeHolder.setY(y - 25f);shapeHolder.setPaint(paint);balls.add(shapeHolder);return shapeHolder;}@Overrideprotected void onDraw(Canvas canvas) {for (int i = 0; i < balls.size(); ++i) {ShapeHolder shapeHolder = (i);canvas.save();X(), Y());Shape().draw(canvas);store();}}}
}
ample.custom.animation;aphics.Paint;
aphics.RadialGradient;
aphics.drawable.ShapeDrawable;
aphics.drawable.shapes.Shape;
import android.view.View;public class ShapeHolder {private float x = 0, y = 0;private int color;private float alpha = 1f;private Paint paint;private ShapeDrawable shape;private RadialGradient gradient;public void setPaint(Paint value) {paint = value;}public Paint getPaint() {return paint;}public void setX(float value) {x = value;}public float getX() {return x;}public void setY(float value) {y = value;}public float getY() {return y;}public void setShape(ShapeDrawable value) {shape = value;}public ShapeDrawable getShape() {return shape;}public int getColor() {return color;}public void setColor(int value) {Paint().setColor(value);color = value;}public void setGradient(RadialGradient value) {gradient = value;}public RadialGradient getGradient() {return gradient;}public void setAlpha(float alpha) {this.alpha = alpha;shape.setAlpha((int)((alpha * 255f) + .5f));}public float getWidth() {Shape().getWidth();}public void setWidth(float width) {Shape s = Shape();s.resize(width, s.getHeight());}public float getHeight() {Shape().getHeight();}public void setHeight(float height) {Shape s = Shape();s.Width(), height);}public ShapeHolder(ShapeDrawable s) {shape = s;}
}
本文发布于:2024-02-01 12:26:49,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170676161136586.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |