Android属性动画

文章目录

    • 属性动画
    • ValueAnimator
    • ObjectAnimator
        • 旋转动画
        • 平移动画
        • 缩放动画
        • 透明度动画
        • 组合动画
          • 方式一:Java代码设置
          • 方式二:XML代码设置
    • TypeEvaluator(估值器)
    • ObjectAnimator高级用法

属性动画

  • 属性动画(Property Animation)是在 Android 3.0(API 11)后才提供的一种全新动画模式
  • 补间动画还有一个缺陷,就是它只能够实现移动、缩放、旋转和淡入淡出这四种动画操作,是改变了View的视觉效果,而不会真正去改变View的属性
  • 属性动画的实现机制是通过对目标对象进行赋值并修改其属性来实现的 。

ValueAnimator

  1. ValueAnimator是整个属性动画机制当中最核心的一个类。
  2. 属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的 。

常用 方法属性

ofInt(),ofFloat(),ofObject:创建ValueAnimator实例
animator.setDuration(1000):设置动画持续时间
animator.setRepeatCount(3):设置重复次数
animator.addUpdateListener():监听器

举个例子:

ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float value = (float) animation.getAnimatedValue();
        Log.e("TAG", "value:" + value);
    }
});
animator.start();

输出信息:

value:0.080379754
value:0.24954662
value:0.29567537
...
value:0.9971504
value:0.9992871
value:1.0

Android属性动画_第1张图片

ObjectAnimator

ObjectAnimator可以直接对任意对象的任意属性进行动画操作的虽说ObjectAnimator会更加常用一些,但是它其实是继承自ValueAnimator的

旋转动画

//将TextView进行一次360度的旋转
ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "rotation", 0f, 360f);
animator.setDuration(2500);
animator.setRepeatCount(3);
animator.start();

平移动画

float distance = textView.getTranslationX();
//将TextView先向左移出屏幕,然后再移动回来
ObjectAnimator translation = ObjectAnimator.ofFloat(textView, "translationX", distance, -500f, distance);
translation.setDuration(2500);
translation.start();

缩放动画

//TextView在垂直方向上放大3倍再还原
ObjectAnimator scale = ObjectAnimator.ofFloat(textView, "scaleY", 1f, 3f, 1f);
scale.setDuration(2500);
scale.start();

透明度动画

//TextView透明变化
ObjectAnimator alpha = ObjectAnimator.ofFloat(textView, "alpha", 1f, 0f, 1f);
alpha.setDuration(2500);
alpha.start();

组合动画

方式一:Java代码设置
float dis = textView.getTranslationX();
// after(Animator anim)   将现有动画插入到传入的动画之后执行
// after(long delay)   将现有动画延迟指定毫秒后执行
// before(Animator anim)   将现有动画插入到传入的动画之前执行
// with(Animator anim)   将现有动画和传入的动画同时执行
ObjectAnimator move = ObjectAnimator.ofFloat(textView, "translationX", dis, -500f, dis);
ObjectAnimator rotate = ObjectAnimator.ofFloat(textView, "rotation", 0f, 360f);
ObjectAnimator fade = ObjectAnimator.ofFloat(textView, "alpha", 1f, 0f, 1f);
AnimatorSet animatorSet = new AnimatorSet();
//顺序执行
//animatorSet.playSequentially(move,rotate,fade);
//执行顺序:move -> rotate -> fade
animatorSet.play(rotate).before(fade).after(move);
animatorSet.setDuration(5000);
animatorSet.start();
方式二:XML代码设置

在res/animator下,定义一个animator_set.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
    <set android:ordering="sequentially">
        <objectAnimator
            android:duration="1000"
            android:propertyName="translationX"
            android:valueFrom="0"
            android:valueTo="-500"
            android:valueType="floatType" />
        <objectAnimator
            android:duration="1000"
            android:propertyName="translationX"
            android:valueFrom="-500"
            android:valueTo="0"
            android:valueType="floatType" />
    set>

    <objectAnimator
        android:duration="2000"
        android:propertyName="rotation"
        android:valueFrom="0"
        android:valueTo="360"
        android:valueType="floatType" />
    <objectAnimator
        android:duration="2000"
        android:propertyName="alpha"
        android:valueFrom="0"
        android:valueTo="1"
        android:valueType="floatType" />
set>
Animator anim= AnimatorInflater.loadAnimator(this,R.animator.animator_set);
anim.setTarget(textView);
anim.start();

TypeEvaluator(估值器)

作用:设置属性值从初始值过渡到结束值的变化具体数值

public class FloatEvaluator implements TypeEvaluator {
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        float startFloat = ((Number) startValue).floatValue();
        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
    }
}


ValueAnimator valueAnimator = ValueAnimator.ofObject(new FloatEvaluator(), 0f, 1f);
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float value = (float) animation.getAnimatedValue();
        Log.e("TAG", "value:" + value);
    }
});
valueAnimator.start();

打印信息

value:0.0
value:0.0
value:0.033116043
value:0.26119065
...
value:0.89794815
value:0.97329646
value:1.0

ObjectAnimator高级用法

Android属性动画_第2张图片

public class MyAnimView extends View {
    public static final int RADIUS = 50;
    private Point currentPoint;
    private Paint mPaint;

    public MyAnimView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.BLUE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (currentPoint == null) {
            currentPoint = new Point(RADIUS, RADIUS);
            drawCircle(canvas);
            startAnimation();
        } else {
            drawCircle(canvas);
        }
    }

    private void drawCircle(Canvas canvas) {
        float x = currentPoint.x;
        float y = currentPoint.y;
        canvas.drawCircle(x, y, RADIUS, mPaint);
    }

    private void setColor(String color) {
        mPaint.setColor(Color.parseColor(color));
    }

    private void startAnimation() {
        Point startPoint = new Point(RADIUS, RADIUS);
        Point endPoint = new Point(getWidth(), getHeight());

        ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentPoint = (Point) animation.getAnimatedValue();
                invalidate();
            }
        });

        ObjectAnimator anim2 = ObjectAnimator.ofObject(this, "color", new ColorEvaluator(), "#0000FF", "#FF0000");
        anim2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                setColor((String) animation.getAnimatedValue());
                invalidate();
            }
        });

        AnimatorSet animSet = new AnimatorSet();
        animSet.play(anim).with(anim2);
        animSet.setDuration(5000);
        //速度加快
        //animSet.setInterpolator(new AccelerateInterpolator(2f));
        //弹跳效果
        animSet.setInterpolator(new BounceInterpolator());
        animSet.start();
    }

    public class PointEvaluator implements TypeEvaluator {

        @Override
        public Object evaluate(float fraction, Object startValue, Object endValue) {
            //fraction:动画的完成度
            Point startPoint = (Point) startValue;
            Point endPoint = (Point) endValue;
            int x = (int) (startPoint.x + fraction * endPoint.x - startPoint.x);
            int y = (int) (startPoint.y + fraction * endPoint.y - startPoint.y);
            Point point = new Point(x, y);
            return point;
        }
    }

    public class ColorEvaluator implements TypeEvaluator {
        private int mRed = -1;
        private int mGreen = -1;
        private int mBlue = -1;

        @Override
        public Object evaluate(float fraction, Object startValue, Object endValue) {
            String startColor = (String) startValue;
            String endColor = (String) endValue;

            int startRed = Integer.parseInt(startColor.substring(1, 3), 16);
            int startGreen = Integer.parseInt(startColor.substring(3, 5), 16);
            int startBlue = Integer.parseInt(startColor.substring(5, 7), 16);
            int endRed = Integer.parseInt(endColor.substring(1, 3), 16);
            int endGreen = Integer.parseInt(endColor.substring(3, 5), 16);
            int endBlue = Integer.parseInt(endColor.substring(5, 7), 16);

            // 初始化颜色的值
            if (mRed == -1) {
                mRed = startRed;
            }
            if (mGreen == -1) {
                mGreen = startGreen;
            }
            if (mBlue == -1) {
                mBlue = startBlue;
            }

            // 计算初始颜色和结束颜色之间的差值
            int redDiff = Math.abs(startRed - endRed);
            int greenDiff = Math.abs(startGreen - endGreen);
            int blueDiff = Math.abs(startBlue - endBlue);
            int colorDiff = redDiff + greenDiff + blueDiff;

            if (mRed != endRed) {
                mRed = getCurrentColor(startRed, endRed, colorDiff, 0, fraction);
            } else if (mGreen != endGreen) {
                mGreen = getCurrentColor(startGreen, endGreen, colorDiff, redDiff, fraction);
            } else if (mBlue != endBlue) {
                mBlue = getCurrentColor(startBlue, endBlue, colorDiff, redDiff + greenDiff, fraction);
            }
            
            // 将计算出的当前颜色的值组装返回
            String currentColor = "#" + getHexString(mRed) + getHexString(mGreen) + getHexString(mBlue);
            return currentColor;
        }

        /**
         * 根据fraction值来计算当前的颜色。
         */
        private int getCurrentColor(int startColor, int endColor, int colorDiff,
                                    int offset, float fraction) {
            int currentColor;
            if (startColor > endColor) {
                currentColor = (int) (startColor - (fraction * colorDiff - offset));
                if (currentColor < endColor) {
                    currentColor = endColor;
                }
            } else {
                currentColor = (int) (startColor + (fraction * colorDiff - offset));
                if (currentColor > endColor) {
                    currentColor = endColor;
                }
            }
            return currentColor;
        }

        /**
         * 将10进制颜色值转换成16进制。
         */
        private String getHexString(int value) {
            String hexString = Integer.toHexString(value);
            if (hexString.length() == 1) {
                hexString = "0" + hexString;
            }
            return hexString;
        }
    }
}

代码下载

你可能感兴趣的:(Android)