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. HTML5的WebGL实现的3D和2D拓扑树

    在HT for Web中2D和3D应用都支持树状结构数据的展示,展现效果各异,2D上的树状结构在展现层级关系明显,但是如果数据量大的话,看起来就没那么直观,找到指定的节点比较困难,而3D上的树状结构在 ...

  2. 使用Python进行GUI操作自动化

    前言 本文介绍怎样使用Python进行跨平台的GUI操作的,其中使用的一个工具包是pyautogui,PyAutoGUI可以模拟鼠标的移动.点击.拖拽,键盘按键输入.按住操作,以及鼠标+键盘的热键同时 ...

  3. SQL2005四个排名函数(row_number、rank、dense_rank和ntile)的比较

    排名函数是SQL Server2005新加的功能.在SQL Server2005中有如下四个排名函数: .row_number .rank .dense_rank .ntile 下面分别介绍一下这四个 ...

  4. DB表的关系及EF中Fluent API的使用

    现在使用多数的数据库是关系型数据库,那么表与表之间的关系就会显得尤其重要,对于数据的CRUD处理和以后数据的分析有很大的好处.下面是对于数据库中对表关系的理解以及在EF中使用Fluent API来创建 ...

  5. var 的使用

    List<Enterprise> epList = ViewBag.epList; foreach (var item in epList){ //todo ... } 当 List< ...

  6. ASP.NET里的Session详细解释

    Session模型简介 Session是什么呢?简单来说就是服务器给客户端的一个编号.当一台WWW服务器运行时,可能有若干个用户浏览正在运正在这台服务器上的网站.当每个用户首次与这台WWW服务器建立连 ...

  7. iOS 阶段学习第十天笔记(结构体)

    iOS学习(C语言)知识点整理 一.数据结构 1)概念:数据结构是指计算机程序中所操作的对象——数据以及数据元素之间的相互关系和运算. 2)结构体必须有struct 关键字修饰. 实例代码: stru ...

  8. ASP.NET MVC 模块与组件(二)——定制图片验证码

     本着简洁直接,我们就直奔主题吧! 下面是一个生成数字和字母随机组合的验证码类源代码: using System; using System.Drawing; using System.Drawing ...

  9. 最近Google经常打不开?

    最近听好多同事讲google打不开,无法进行搜索,用了代理之后速度还是很慢,而百度搜索又不佳… 就在此分享一些google地址: 个人收藏夹的: 203.208.46.144(这段时间推荐使用这4个地 ...

  10. java必看书籍

    Java核心技术 卷1 基础知识(第9版)Java核心技术 卷II 高级特性(第9版) 数据库系统概念(原书第6版)Oracle 从入门到精通MySQL数据库应用从入门到精通 Java并发编程实战(第 ...