Android属性动画

2020-04-29  本文已影响0人  Sky_Blue
一、属性动画
  1. 定义属性
  2. 提供get set方法
  3. 使用ObjectAnimator
二、ObjectAnimator 、PropertyValuesHolder 用法
public class CircleView extends View {
    private Paint mPaint;
    private float radius;

    public CircleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
    }

    public float getRadius() {
        return radius;
    }


    public void setRadius(float radius) {
        this.radius = radius;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, mPaint);
    }
}

public class MainActivity extends AppCompatActivity {

    private CircleView mCircleView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mCircleView = findViewById(R.id.cv);

        // 1. 半径从0到50dp
        ObjectAnimator animator = ObjectAnimator
                .ofFloat(mCircleView,
                        "radius",
                        Utils.dip2px(50)
                );
        animator.setDuration(1500);
        animator.setStartDelay(1000);
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // 2. 从左向右移动:中间慢两边快
                translate();
            }
        });
        animator.start();
    }

    private void translate() {
        // 2. 从左向右移动:中间慢两边快
        int width = ((ViewGroup) mCircleView.getParent()).getWidth()-Utils.dip2px(200);
        Keyframe frame1=Keyframe.ofFloat(0.0f,0);
        Keyframe frame2=Keyframe.ofFloat(0.1f,0.2f*width);
        Keyframe frame3=Keyframe.ofFloat(0.8f,0.6f*width);
        Keyframe frame4=Keyframe.ofFloat(0.9f,0.9f*width);
        Keyframe frame5=Keyframe.ofFloat(1f,1f*width);
        PropertyValuesHolder holder=PropertyValuesHolder.ofKeyframe("translationX",
                frame2,frame3,frame1,frame4,frame5);
        ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mCircleView, holder);
        animator.setDuration(1500);
        animator.start();
        
    }
}
三、TypeEvaluator用法
public class PointView extends View {
    private Point point = new Point(0, 0);
    private Paint mPaint;
    private int radius = Utils.dip2px(25);

    public PointView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
    }

    public Point getPoint() {
        return point;
    }

    public void setPoint(Point point) {
        this.point = point;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 绘制一个圆:
        canvas.drawCircle(point.x + radius, point.y + radius, radius, mPaint);
    }
}

public class MainActivity extends AppCompatActivity {

    private PointView mPointView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPointView = findViewById(R.id.pv);

        // 最终移动的点的位置
        Point endPoint = new Point(Utils.dip2px(200), Utils.dip2px(300));
        // 动画效果:圆按对角线移动
        ObjectAnimator animator = ObjectAnimator.ofObject(mPointView, "point",
                new PointTypeEvaluator(), endPoint);
        animator.setDuration(2000);
        animator.setInterpolator(new DecelerateInterpolator());
        animator.setStartDelay(1000);
        animator.start();

    }

    /**
     * 自定义TypeEvaluator
     */
    static class PointTypeEvaluator implements TypeEvaluator<Point> {

        @Override
        public Point evaluate(float fraction, Point startValue, Point endValue) {
            // 计算下一个点
            int x = (int) (startValue.x + (endValue.x - startValue.x) * fraction);
            int y = (int) (startValue.y + (endValue.y - startValue.y) * fraction);
            return new Point(x, y);
        }
    }
}
六、综合案例:翻转的View
/**
 * 翻转的View
 */
public class FancyFlipView extends View {
    private Bitmap mBitmap;
    private Paint mPaint;
    private Camera mCamera;
    private int iconWidth;
    private int iconHeight;
    private int mStart;

    // 顶部翻转角度
    private float topFlip=0;
    // 底部翻转角度
    private float bottomFlip=0;
    // 整体旋转角度
    private float flipRotation=0;

    public FancyFlipView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public static final int ICON_WIDTH = 150;

    {
        mCamera = new Camera();

        mCamera.setLocation(0, 0, Utils.getZForCamera());
        mBitmap = Utils.getBitmap(getContext(), R.drawable.icon, Utils.dip2px(ICON_WIDTH));
        iconWidth = mBitmap.getWidth();
        iconHeight = mBitmap.getHeight();
        // 这个值可以随便定
        mStart = iconWidth / 2;
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 整体改成左右了

        // Camera 三维变换: 倒着写

        // 绘制上半部:倒着写
        canvas.save();
        canvas.translate(iconWidth / 2 + mStart, iconHeight / 2+mStart);
        canvas.rotate(-flipRotation);
        mCamera.save();
        mCamera.rotateY(topFlip);// 底部翻转
        mCamera.applyToCanvas(canvas);
        mCamera.restore();
        canvas.clipRect(-iconWidth , -iconHeight , 0 , iconHeight);
        canvas.rotate(flipRotation);
        canvas.translate(-(iconWidth / 2 + mStart), -(iconHeight / 2+mStart));
        canvas.drawBitmap(mBitmap, mStart, mStart, mPaint);
        canvas.restore();

        // 绘制下半部:倒着写
        // 1. 将图片中心点移动到左上角
        // 2. 旋转图片
        // 2. 裁剪图片下半部分
        // 3. 将图片中心移回去
        canvas.save();
        canvas.translate(iconWidth / 2 + mStart, iconHeight / 2+mStart);
        canvas.rotate(-flipRotation);
        mCamera.save();
        mCamera.rotateY(bottomFlip);// 底部翻转
        mCamera.applyToCanvas(canvas);
        mCamera.restore();
        canvas.clipRect(0 , -iconHeight, iconWidth , iconHeight );
        canvas.rotate(flipRotation);
        canvas.translate(-(iconWidth / 2 + mStart), -(iconHeight / 2+mStart));
        canvas.drawBitmap(mBitmap, mStart, mStart, mPaint);
        canvas.restore();

    }

    public float getTopFlip() {
        return topFlip;
    }

    public void setTopFlip(float topFlip) {
        this.topFlip = topFlip;
        invalidate();
    }

    public float getBottomFlip() {
        return bottomFlip;
    }

    public void setBottomFlip(float bottomFlip) {
        this.bottomFlip = bottomFlip;
        invalidate();
    }

    public float getFlipRotation() {
        return flipRotation;
    }

    public void setFlipRotation(float flipRotation) {
        this.flipRotation = flipRotation;
        invalidate();
    }
}

public class MainActivity extends AppCompatActivity {

    private FancyFlipView mFlipView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mFlipView = findViewById(R.id.pv);

        // 右边向中间翻转45度
        ObjectAnimator bottomFlip = ObjectAnimator.ofFloat(mFlipView, "bottomFlip", -45);
        bottomFlip.setDuration(500);

        // 旋转270度:Y 轴和 X轴相当于对换
        ObjectAnimator flipRotation = ObjectAnimator.ofFloat(mFlipView, "flipRotation", 270);
        flipRotation.setDuration(1500);

        // 左边向中间翻转45度(旋转270度后,这条边在上面了)
        ObjectAnimator topFlip = ObjectAnimator.ofFloat(mFlipView, "topFlip", 45);
        topFlip.setDuration(500);

        AnimatorSet set=new AnimatorSet();
        set.setStartDelay(500);
        // 按顺序执行
        set.playSequentially(bottomFlip,flipRotation,topFlip);
        set.start();
    }


}
上一篇下一篇

猜你喜欢

热点阅读