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


     

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

      可以用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

  • 相关阅读:
    D11 列表 list 元祖 字典dict
    D10 基本数据类型(各种职业的技能分析) 主要为 int 和 str
    Python D9 学习
    面向对象方法传参实现数组求和,求平均值
    用带参数的方法给空数组放元素,寻找数组里面的值是否存在。
    两种方法把类和对象写在同一个文件内
    创建一个管理员对象,输入正确用户名和密码,可以修改密码(类和对象分为两个文件,区别于放在一个文件内)
    创建一个游客对象,输入信息判断游客年龄是否免费游览
    建立一个学生对象,输出学生信息
    把输入的数字转为数组,拿出其中的最小值
  • 原文地址:https://www.cnblogs.com/mengdd/p/3303403.html
Copyright © 2020-2023  润新知