Android Animation学习(四) ApiDemos解析:多属性动画

  如果想同时改变多个属性,根据前面所学的,比较显而易见的一种思路是构造多个对象Animator ,

  ( Animator可以是ValueAnimatorObjectAnimatorAnimatorSet

  然后最后把它们放在一个AnimatorSet中。

  另一种思路就是,把多个属性的改变放在同一个 ValueAnimator 中(ObjectAnimator也是 ValueAnimator)。

  而这就要借助PropertyValuesHolder。本文主要讲这种方法。

  

PropertyValuesHolder

  PropertyValuesHolder是API Level 11加进来的。根据名字就可以判断出它是某种属性的持有者。

  使用工厂方法构造PropertyValuesHolder对象,指定属性名和一系列属性值。

  代码例子:MultiPropertyAnimation中:

                // ============================================================
// 第二个小球:加速下落并且alpha变化
ball = balls.get(1); // 利用ofFloat工厂方法构造PropertyValuesHolder类型对象,控制y属性
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y",
ball.getY(), getHeight() - BALL_SIZE);
// 利用ofFloat工厂方法构造另一个PropertyValuesHolder类型对象,控制alpha属性
PropertyValuesHolder pvhAlpha = PropertyValuesHolder.ofFloat(
"alpha", 1.0f, 0f);
// 利用ofPropertyValuesHolder方法来构造ObjectAnimator对象
// 把多个属性变化结合到一个动画中去
ObjectAnimator yAlphaBouncer = ObjectAnimator
.ofPropertyValuesHolder(ball, pvhY, pvhAlpha)
.setDuration(DURATION / 2);
yAlphaBouncer.setInterpolator(new AccelerateInterpolator());
yAlphaBouncer.setRepeatCount(1);
yAlphaBouncer.setRepeatMode(ValueAnimator.REVERSE);

 

关键帧Keyframe

  PropertyValuesHolder的工厂方法里面,除了整形ofInt()、浮点型ofFloat()、Object类型ofObject()之外,还有一种:ofKeyframe()。

  Keyframe类型对象由一个time/value对组成,定义了指定时间点的指定值。

  

  每一个keyframe还可以拥有自己的interpolator,控制了前一个关键帧到这一个关键帧之间的时间动画行为。

  Keyframe 对象的构造也用是工厂方法:ofInt()ofFloat(), or ofObject()

  Keyframe对象构造完之后就可以用 ofKeyframe()工厂方法来构造PropertyValuesHolder对象。

  代码例子:MultiPropertyAnimation中:

                // ============================================================
// 第四个小球:利用关键帧实现曲线运动
ball = balls.get(3);
// 属性1:Y坐标运动:下落
pvhY = PropertyValuesHolder.ofFloat("y", ball.getY(),
getHeight() - BALL_SIZE);
float ballX = ball.getX();
// 三个关键帧
Keyframe kf0 = Keyframe.ofFloat(0f, ballX);
Keyframe kf1 = Keyframe.ofFloat(.5f, ballX + 100f);
Keyframe kf2 = Keyframe.ofFloat(1f, ballX + 50f);
// 属性2:X坐标运动:曲折
// 用三个关键帧构造PropertyValuesHolder对象
PropertyValuesHolder pvhX = PropertyValuesHolder.ofKeyframe(
"x", kf0, kf1, kf2); // 再用两个PropertyValuesHolder对象构造一个ObjectAnimator对象
ObjectAnimator yxBouncer = ObjectAnimator
.ofPropertyValuesHolder(ball, pvhY, pvhX).setDuration(
DURATION / 2);
yxBouncer.setRepeatCount(1);
yxBouncer.setRepeatMode(ValueAnimator.REVERSE);

View的多属性动画:使用ViewPropertyAnimator

  ViewPropertyAnimatorAPI Level 12引进的。

  它是用来做针对View对象的多个属性动画功能。

  (前面的PropertyValuesHolder对象是针对所有对象的,范围更广)。

  如果要同时变换一个View的多个属性的话,ViewPropertyAnimator提供了一种更方便和更适合的方法。

  而且由于多个属性的invalidate方法调用统一管理,而不是之前的分别调用,所以还会有一些性能优化。

  注意 ViewPropertyAnimator 这个类的对象不是由调用者构造的,而是通过View类的animate()方法返回的。

  比如下面的代码对比:给同一个View实现同一个动画效果:

  用多个ObjectAnimator对象:

ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();

  用一个ObjectAnimator对象加多个PropertyValuesHolder:

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();

  用ViewPropertyAnimator:

myView.animate().x(50f).y(100f);

API Demos完整代码:

public class MultiPropertyAnimation extends Activity {

    private static final int DURATION = 1500;

    @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animation_multi_property);
LinearLayout container = (LinearLayout) findViewById(R.id.container);
final MyAnimationView animView = new MyAnimationView(this);
container.addView(animView); Button starter = (Button) findViewById(R.id.startButton);
starter.setOnClickListener(new View.OnClickListener() { public void onClick(View v) {
animView.startAnimation(); }
}); } public class MyAnimationView extends View implements
ValueAnimator.AnimatorUpdateListener { private static final float BALL_SIZE = 100f; public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>();
AnimatorSet animation = null;
Animator bounceAnim = null;
ShapeHolder ball = null; public MyAnimationView(Context context) {
super(context);
addBall(50, 0);
addBall(150, 0);
addBall(250, 0);
addBall(350, 0);
} private void createAnimation() {
if (bounceAnim == null) {
ShapeHolder ball; // ============================================================
// 第一个小球:弹跳效果
ball = balls.get(0);
ObjectAnimator yBouncer = ObjectAnimator.ofFloat(ball, "y",
ball.getY(), getHeight() - BALL_SIZE).setDuration(
DURATION);
yBouncer.setInterpolator(new BounceInterpolator());
yBouncer.addUpdateListener(this); // ============================================================
// 第二个小球:加速下落并且alpha变化
ball = balls.get(1); // 利用ofFloat工厂方法构造PropertyValuesHolder类型对象,控制y属性
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y",
ball.getY(), getHeight() - BALL_SIZE);
// 利用ofFloat工厂方法构造另一个PropertyValuesHolder类型对象,控制alpha属性
PropertyValuesHolder pvhAlpha = PropertyValuesHolder.ofFloat(
"alpha", 1.0f, 0f);
// 利用ofPropertyValuesHolder方法来构造ObjectAnimator对象
// 把多个属性变化结合到一个动画中去
ObjectAnimator yAlphaBouncer = ObjectAnimator
.ofPropertyValuesHolder(ball, pvhY, pvhAlpha)
.setDuration(DURATION / 2);
yAlphaBouncer.setInterpolator(new AccelerateInterpolator());
yAlphaBouncer.setRepeatCount(1);
yAlphaBouncer.setRepeatMode(ValueAnimator.REVERSE); // ============================================================
// 第三个小球:宽度,高度,x,y同时变化
ball = balls.get(2);
PropertyValuesHolder pvhW = PropertyValuesHolder.ofFloat(
"width", ball.getWidth(), ball.getWidth() * 2);
PropertyValuesHolder pvhH = PropertyValuesHolder.ofFloat(
"height", ball.getHeight(), ball.getHeight() * 2);
PropertyValuesHolder pvTX = PropertyValuesHolder.ofFloat("x",
ball.getX(), ball.getX() - BALL_SIZE / 2f);
PropertyValuesHolder pvTY = PropertyValuesHolder.ofFloat("y",
ball.getY(), ball.getY() - BALL_SIZE / 2f);
// 利用ofPropertyValuesHolder方法来构造ObjectAnimator对象
// 因为是可变参数,所以PropertyValuesHolder对象的个数不限
ObjectAnimator whxyBouncer = ObjectAnimator
.ofPropertyValuesHolder(ball, pvhW, pvhH, pvTX, pvTY)
.setDuration(DURATION / 2);
whxyBouncer.setRepeatCount(1);
whxyBouncer.setRepeatMode(ValueAnimator.REVERSE); // ============================================================
// 第四个小球:利用关键帧实现曲线运动
ball = balls.get(3);
// 属性1:Y坐标运动:下落
pvhY = PropertyValuesHolder.ofFloat("y", ball.getY(),
getHeight() - BALL_SIZE);
float ballX = ball.getX();
// 三个关键帧
Keyframe kf0 = Keyframe.ofFloat(0f, ballX);
Keyframe kf1 = Keyframe.ofFloat(.5f, ballX + 100f);
Keyframe kf2 = Keyframe.ofFloat(1f, ballX + 50f);
// 属性2:X坐标运动:曲折
// 用三个关键帧构造PropertyValuesHolder对象
PropertyValuesHolder pvhX = PropertyValuesHolder.ofKeyframe(
"x", kf0, kf1, kf2); // 再用两个PropertyValuesHolder对象构造一个ObjectAnimator对象
ObjectAnimator yxBouncer = ObjectAnimator
.ofPropertyValuesHolder(ball, pvhY, pvhX).setDuration(
DURATION / 2);
yxBouncer.setRepeatCount(1);
yxBouncer.setRepeatMode(ValueAnimator.REVERSE); // ===========================================================
// 所有小球动画的集合
bounceAnim = new AnimatorSet();
((AnimatorSet) bounceAnim).playTogether(yBouncer,
yAlphaBouncer, whxyBouncer, yxBouncer);
}
} public void startAnimation() {
createAnimation();
bounceAnim.start();
} 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);
shapeHolder.setY(y);
int red = (int) (100 + Math.random() * 155);
int green = (int) (100 + Math.random() * 155);
int blue = (int) (100 + Math.random() * 155);
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);
balls.add(shapeHolder);
return shapeHolder;
} @Override
protected void onDraw(Canvas canvas) {
for (ShapeHolder ball : balls) {
canvas.translate(ball.getX(), ball.getY());
ball.getShape().draw(canvas);
canvas.translate(-ball.getX(), -ball.getY());
}
} public void onAnimationUpdate(ValueAnimator animation) {
invalidate();
} }
}

  

参考资料:

  API Guides:Property Animation

  http://developer.android.com/guide/topics/graphics/prop-animation.html

  项目地址:https://github.com/mengdd/AnimationApiDemos.git

Android Animation学习(四) ApiDemos解析:多属性动画的更多相关文章

  1. Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition

    Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition Property animation系统还提供了对ViewGroup中的View改变 ...

  2. Android Animation学习(三) ApiDemos解析:XML动画文件的使用

    Android Animation学习(三) ApiDemos解析:XML动画文件的使用 可以用XML文件来定义Animation. 文件必须有一个唯一的根节点: <set>, <o ...

  3. Android Animation学习(二) ApiDemos解析:基本Animators使用

    Android Animation学习(二) ApiDemos解析:基本Animatiors使用 Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.O ...

  4. Android Animation学习(二) ApiDemos解析:基本Animatiors使用

    Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.ObjectAnimator.AnimatorSet ApiDemos中Animation部分是单独 ...

  5. Android Animation学习(六) View Animation介绍

    Android Animation学习(六) View Animation介绍 View Animation View animation系统可以用来执行View上的Tween animation和F ...

  6. Android Animation学习(一) Property Animation原理介绍和API简介

    Android Animation学习(一) Property Animation介绍 Android Animation Android framework提供了两种动画系统: property a ...

  7. Android JNI学习(四)——JNI的常用方法的中文API

    本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...

  8. Android Animation学习笔记

    原文地址: http://www.cnblogs.com/feisky/archive/2010/01/11/1644482.html 关于动画的实现,Android提供了Animation,在And ...

  9. Android animation学习笔记之view/drawable animation

    前一章中总结了android animation中property animation的知识和用法,这一章总结View animation和Drawable animation的有关知识: View ...

随机推荐

  1. Unsafe的应用

    要想把java并发包学好,并明白其底层的设计原理,Unsafe类你不能不去研究一下.下面介绍一下Unsafe类的功能以及它在JDK中的应用. 一.分配内存和释放内存 功能:类中提供的3个本地方法all ...

  2. 十五个常用的jquery代码段【转】

    好的文章顶一个 回到顶部按钮 通过使用 jQuery 中的 animate 和 scrollTop 方法,你无需插件便可创建一个简单地回到顶部动画: 1 // Back to top 2 $('a.t ...

  3. 绘制SVG内容到Canvas的HTML5应用

    SVG与Canvas是HTML5上绘制图形应用的两种完全不同模式的技术,两种绘制图形方式各有优缺点,但两者并非水火不容,尤其是SVG内容可直接绘制在Canvas上的功能,使得两者可以完美的融合在一起, ...

  4. Android Studio导入项目非常慢的解决办法

    问题 Android Studio目前已经更新到2.0 Preview 6了,作为Google大力推崇的开发工具,相对于Eclipse ADT有着不可比拟的优势.然而在实际使用时,依然有不少不爽的地方 ...

  5. TRichTextBox – A universal RichTextBox which can display animated images and more

    TRichTextBox – A universal RichTextBox which can display animated images and more trestan, 7 Dec 201 ...

  6. NET RichTextBox控件如何可以插入图像

    本文介绍.NET RichTextBox控件如何可以插入图像,控制和ActiveX对象通过使用OLE方式,如在解释,.不幸的是,它涵盖了只用一个C源代码样本,所以我需要在托管代码(C#)实施类似的解决 ...

  7. LeetCode - Balanced Binary Tree

    题目: Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced bin ...

  8. 【SQL】分享表值函数FMakeRows,用于生成行

    ------------更新:201501071730------------ 评论中又有一位[笑东风]兄给出改善建议,在此先感谢他.原理是借助行数较多的一个系统视图sys.all_columns与自 ...

  9. echarts 折线图动态x轴及数据

    <!DOCTYPE html><html lang="en"><head> <meta charset="utf-8" ...

  10. 近乎(Spacebuilder)移动端 V2.2 发布,SNS 社区开源软件

    本次新版本是在以往版本基础上的进一步优化,尤其是架构和操作体验方面. 架构方面: 近乎团队在此次改版中摒弃了原有的缓存框架,启用更加清晰.易于维护的近乎V2.2结构框架,提升了产品的开发效率和拓展性, ...