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

本文介绍如何使用XML文件定义Android中的Property动画,包括ObjectAnimator、ValueAnimator及AnimatorSet的使用方式。并通过实例展示了不同类型的动画效果及其加载方法。

可以用XML文件来定义Animation。

  文件必须有一个唯一的根节点:

  <set>, <objectAnimator>, or <valueAnimator>三者之一。

  对应的Java类是:

 

  <set>标签是可以嵌套的。

  <set>标签的android:ordering属性规定了这个set中的动画的执行顺序。该属性值默认是together (default)。

  比如:

复制代码
<set android:ordering="sequentially" >

    <set> <objectAnimator android:duration="500" android:propertyName="x" android:valueTo="400" android:valueType="intType" /> <objectAnimator android:duration="500" android:propertyName="y" android:valueTo="300" android:valueType="intType" /> </set> <objectAnimator android:duration="500" android:propertyName="alpha" android:valueTo="1f" /> </set>
复制代码

 

  

  使用时:

        AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(
                myContext, R.anim.property_animator);
        set.setTarget(myObject);
        set.start();

 


  为了区分Property animation和View animation的资源文件,从Android 3.1开始,Property animation的xml文件存在res/animator/目 录下(View animation的存在res/anim/目录下), animator这个名是可选的。但是如果你想要使用Eclipse ADT plugin (ADT 11.0.0+)的布局编辑器,你就必须使用res/animator/目录,因为ADT只在该目录下寻找property animation的资源文件。

 

 

Api Demo相关代码:

  代码结构和上一篇文章中的基本类似,也是各种小球的动画,只不过这次的动画效果都是从XML文件中读取的。

  完整的项目见项目地址:https://github.com/mengdd/AnimationApiDemos.git

复制代码
public class AnimationFromXmlActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 设置布局,布局xml中只包含了一个线性布局和一个Button  setContentView(R.layout.animation_basic); LinearLayout container = (LinearLayout) findViewById(R.id.container); // 将自定义的View加入到线性布局中 final MyAnimationView animView = new MyAnimationView(this); container.addView(animView); // Button的点击事件即动画开始 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>(); Animator animation = null; public MyAnimationView(Context context) { super(context); addBall(50, 50); addBall(200, 50); addBall(350, 50); addBall(500, 50, Color.GREEN); } private void createAnimation() { Context appContext = AnimationFromXmlActivity.this; if (animation == null) { // ======================================================== // 载入根节点为<objectAnimator>的xml资源文件,解析放进ObjectAnimator类对象 ObjectAnimator anim = (ObjectAnimator) AnimatorInflater .loadAnimator(appContext, R.anim.object_animator); anim.addUpdateListener(this); anim.setTarget(balls.get(0)); // ======================================================== // 载入根节点为<animator>的xml资源文件,解析放进ValueAnimator类对象 ValueAnimator fader = (ValueAnimator) AnimatorInflater .loadAnimator(appContext, R.anim.animator); fader.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { invalidate(); // ValueAnimator动画需要在监听器中自己设置对象的属性值 // 这里改变的是alpha值 balls.get(1).setAlpha( (Float) animation.getAnimatedValue()); } }); // ======================================================== // 载入根节点为<set>的xml资源文件,解析放进AnimatorSet类对象 AnimatorSet seq = (AnimatorSet) AnimatorInflater.loadAnimator( appContext, R.anim.animator_set);// x和y属性同时改变的动画集合 seq.setTarget(balls.get(2)); // 这里要注意:因为AnimatorSet没有设置AnimatorUpdateListener的方法, // 所以如果其他动画没有设置AnimatorUpdateListener来进行View的invalidate()刷新, // 这个AnimatorSet seq是不刷新的 // ======================================================== // 载入根节点为<objectAnimator>的xml资源文件,解析放进ObjectAnimator类对象 ObjectAnimator colorizer = (ObjectAnimator) AnimatorInflater .loadAnimator(appContext, R.anim.color_animator); colorizer.setTarget(balls.get(3)); colorizer.addUpdateListener(this); // ======================================================== // 总的AnimationSet,所有的动画同时播放 animation = new AnimatorSet(); ((AnimatorSet) animation).playTogether(anim, fader, seq, colorizer); } } public void startAnimation() { createAnimation(); animation.start(); } private ShapeHolder createBall(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); return shapeHolder; } private void addBall(float x, float y, int color) { ShapeHolder shapeHolder = createBall(x, y); shapeHolder.setColor(color); balls.add(shapeHolder); } private void addBall(float x, float y) { ShapeHolder shapeHolder = createBall(x, 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 = shapeHolder.getShape().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); balls.add(shapeHolder); } @Override protected void onDraw(Canvas canvas) { // 遍历并绘制每一个球形对象 for (ShapeHolder ball : balls) { // 这里是canvas.translate到一个地方,进行绘制,之后再translate回来 // 跟先save后restore的作用相同  canvas.translate(ball.getX(), ball.getY()); ball.getShape().draw(canvas); canvas.translate(-ball.getX(), -ball.getY()); } } public void onAnimationUpdate(ValueAnimator animation) { // 刷新View  invalidate(); // 因为第一个小球用的是ObjectAnimator,所以这里不必要自己设置属性值 // 如果是ValueAnimator就需要加上下面两行 // ShapeHolder ball = balls.get(0); // ball.setY((Float) animation.getAnimatedValue());  } } }
复制代码

 

相关动画:

  资源文件:

  第一个小球:下落,并且返回:

复制代码
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000" android:valueTo="200" android:valueType="floatType" android:propertyName="y" android:repeatCount="1" android:repeatMode="reverse"/>
复制代码

  第二个小球:消失(变为透明),然后再出现:

复制代码
<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:repeatCount="1" android:repeatMode="reverse"/>
复制代码

 

  第三个小球:X轴与Y轴同时运动,并且返回:

复制代码
<set>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:valueTo="200" android:valueType="floatType" android:propertyName="x" android:repeatCount="1" android:repeatMode="reverse"/> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:valueTo="400" android:valueType="floatType" android:propertyName="y" android:repeatCount="1" android:repeatMode="reverse"/> </set>
复制代码


  第四个小球:颜色变化:

复制代码
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000" android:valueFrom="#0f0" android:valueTo="#00ffff" android:propertyName="color" android:repeatCount="1" android:repeatMode="reverse"/>
复制代码

 

 

参考资料

  API Guides:Declaring Animations in XML

  Animation Resources

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

转载于:https://www.cnblogs.com/Free-Thinker/p/4384198.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值