属性动画
来源:互联网 发布:什么是矩阵音响 编辑:程序博客网 时间:2024/04/29 22:42
属性(Property)动画
属性(Property)动画:安卓提供的众多动画中的一种,从某种角度来看,属性动画实际上是增强版的补间(Tween)动画。
属性动画主要由两方面组成:
1.计算各帧的相关属性值。
2.给指定的对象设置相关的属性值。
区别:
1.补间(Tween)动画只能够操控各种组件的透明度(alpha),位置(translate),
旋转(rotate)和放缩(scale)四种属性进行相应的变换,但是属性(Property)动画可以对任何的属性值做出改变。
2.补间(Tween)动画只能对UI组件作用,但是属性(Property)动画没有限制,可以对任何对象进行操作。
属性动画API:
1.ValueAnimator:属性动画主要的时间引擎,它负责计算各个帧的属性值,也就是属性动画第一组成部分。由于ValueAnimator只会负责第一部分,第二部分给组件赋属性值就需要手动完成。
2.ObjectAnimator:ValueAnimator的子类,在使用的时候可以直接指定组件对象,使用起来更加的方便了。但是在某些场景下,ObjectAnimator存在一些限制,可能需要考虑使用ValueAnimator。
3.AnimatorSet:Animator的子类,可以用于组合多个Animator对象,还可以指定是按次序播放还是同时播放。
在ValueAnimator中还用到了一个计算工具类Evaluator(计算器),控制者属性动画如何计算属性值。Android提供了集中Evaluator:
1.IntEvaluator:用于计算int类型的属性值计算器。
2.FloatEvaluator:用于计算float类型的属性值计算器。
3.ArgbEvaluator:用于计算十六进制的rgb颜色值。
4.TypeEvaluator:计算器的接口,供自定义计算器实现。
使用ValueAnimator创建动画大致如下四个步骤:
1.调用ValueAnimator的ofInt(), ofFloat(), ofObject()静态方法创建ValueAnimator实例,很明显这几个不同的方法创建的不同实例中,所用到的计算器也是不同的。2.调用ValueAnimator的setDuration()等方法给属性动画设置相应的参数,如动画的持续时间,重复次数等。3.调用start()方法启动相应的动画。4.为ValueAnimator注册AnimatorUpdateListener监听器,在监听器中可以实时获取到ValueAnimator计算出来的属性值,只需要在监听器中赋值给对应对象就行了。例如:
ValueAnimator animation = ValueAnimator.ofFloat(1f, 0f); animation.setDuration(3000); animation.setRepeatCount(1); animation.start(); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { /** * 使用的时候可以通过getAnimatedValue()来获取当前计算出来的帧的属性值,并赋值给制定对象。 */ } });
如果是希望使用自己利用TypeEvaluator定义出来的属性值计算器,则将第一步改为:
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(),1f, 0f);
2.使用ObjectAnimator创建动画和ValueAnimator差不多,只不过ObjectAnimator已经实现了将计算结果赋值给对象,我们在使用的时候提供控件对象,
不需要注册AnimatorUpdateListener监听器(没有上述的第四个步骤)。
例如:
ObjectAnimator animation = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f); animation.setDuration(1000); animation.setRepeatCount(1); animation.start();
注意: 1.在使用ObjectAnimator的对象上一定要有改变的属性值,例如上述的例子中imageView一定要有alpha这个属性值。 2.如果在第一句话是
ObjectAnimator animation = ObjectAnimator.ofFloat(imageView, "alpha", 1f);
少提供了一个参数,则提供的值会被认为是属性计算的结束值,对alpha这个属性一定要提供getter方法,返回的值将作为属性计算的初始值,也就是从该组件的当前状态开始执行动画。 3.如果动画的对象是View,为了能显示动画的效果,需要不断的通知组件重新绘制,调用View.invalidate()方法, 但是View定义的setter方法,如setAloha()等方法都会自动的调用invalidate()方法,不需要我们再额外的调用了。
/** * 图形类 * 在实例中是一个圆 */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 ShapeHolder(ShapeDrawable s) { shape = s; } public float getWidth() { return shape.getShape().getWidth(); } public void setWidth(float width) { Shape s = shape.getShape(); s.resize(width,s.getWidth()); } public float getHeight() { return shape.getShape().getHeight(); } public void setHeight(float height) { Shape s = shape.getShape(); s.resize(height,s.getHeight()); } 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 int getColor() { return color; } public void setColor(int color) { this.color = color; } public ShapeDrawable getShape() { return shape; } public void setShape(ShapeDrawable shape) { this.shape = shape; } 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; }}public class MainActivity extends Activity { static final float BALL_SIZE = 50F; /** * 用来控制动画执行的时间 */ static final float FULL_TIME = 1000; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LinearLayout container = (LinearLayout) findViewById(R.id.root); /** * 将自定义控件加入到布局中 */ container.addView(new MyAniamtionView(this)); } /** * 自定义View * 实现了AnimatorUpdateListener监听类 */ public class MyAniamtionView extends View implements ValueAnimator.AnimatorUpdateListener { /** * 存储多个小球的容器 */ public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>(); public MyAniamtionView(Context context) { super(context); setBackgroundColor(Color.WHITE); } @Override public boolean onTouchEvent(MotionEvent event) { //在手指触摸的地方添加一个小球 ShapeHolder newBall = addBall(event.getX(), event.getY()); float startY = newBall.getY(); float endY = getHeight() - BALL_SIZE; float h = (float) getHeight(); float eventY = event.getY(); int duration = (int) (FULL_TIME * ((h - eventY) / h)); //用ValueAnimator定义落下的动画 ValueAnimator fallAnim = ObjectAnimator.ofFloat(newBall, "y", startY, endY); fallAnim.setDuration(duration); fallAnim.setInterpolator(new AccelerateInterpolator()); //用ObjectAnimator定义落下的动画 ObjectAnimator bounceBackAnim = ObjectAnimator.ofFloat(newBall, "y", endY, startY); bounceBackAnim.setDuration(duration); bounceBackAnim.setInterpolator(new DecelerateInterpolator()); fallAnim.addUpdateListener(this); //定义小球透明度的动画 ObjectAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); fadeAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { balls.remove(((ObjectAnimator)animation).getTarget()); } }); fadeAnim.addUpdateListener(this); //定义一个AnimatorSet来将定义的三个动画排序 AnimatorSet animatorSet = new AnimatorSet();animatorSet.play(fallAnim).before(bounceBackAnim); animatorSet.play(bounceBackAnim).before(fadeAnim); animatorSet.start(); return true; } /** * 向小球集合ArrayList中加入小球 * 设置各种属性坐标等 * * @param x * @param y * @return */ private ShapeHolder addBall(float x, float y) { OvalShape circle = new OvalShape(); circle.resize(BALL_SIZE, BALL_SIZE); ShapeDrawable drawable = new ShapeDrawable(circle); ShapeHolder shapeHolder = new ShapeHolder(drawable); shapeHolder.setX(x - BALL_SIZE / 2); shapeHolder.setY(y - BALL_SIZE / 2); 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 drakColor = 0xff000000 | red / 4 << 16 | green / 4 << 8 | blue /4; RadialGradient gradient = new RadialGradient(37.5f, 12.5f, BALL_SIZE, color, drakColor, Shader.TileMode.CLAMP); paint.setShader(gradient); shapeHolder.setPaint(paint); balls.add(shapeHolder); return shapeHolder; } /** * 将集合里的每个小球都绘制在屏幕上面 * @param canvas */ @Override protected void onDraw(Canvas canvas) { for (ShapeHolder shapeHolder : balls) { canvas.save(); canvas.translate(shapeHolder.getX(), shapeHolder.getY()); shapeHolder.getShape().draw(canvas); canvas.restore(); } } @Override public void onAnimationUpdate(ValueAnimator animation) { this.invalidate(); } }}
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 属性动画
- 内核符号表的生成和查找过程
- 关于Class.getResource和ClassLoader.getResource的路径问题
- 抽象工厂模式
- error BK1506 : cannot open file '.\Debug\????????.sbr': No such file or dire
- 编写函数求方程的根
- 属性动画
- Android初学之Android项目结构
- Java学习笔记25
- 【Unity3D】Unity3D中的C#基本语法知识点①(变量与数组)
- poj3253求切割木板开销最少是多少, 赫夫曼编码
- Duang~ Golang 学习初探
- 3.2学习内容:android图片灰度化,VelocityTracker类
- 图片延迟加载——例子
- git私有远程库的建立与使用