Android动画之旅(六)----放大镜的特效动画

Android动画之旅(六)----放大镜的特效动画_第1张图片

动画核心:
1.主要考验动画的拆分,然后分析动画.

2.判断一个动画好与坏,主要是看动画的平滑程度,而能解决动画不平滑需要做很多处理,这就考验做动画的人的能力.

3.mPaint.setStrokeCap(Paint.Cap.ROUND)画笔的笔刷 是方形 还是圆形,看平滑程度.

4.两种控制动画的手段
(1) onDraw{
    switch(status){
        case 0 :
            break;
        case 0 :
            break;
        case 0 :
            break;
        case 0 :
            break;
        case 0 :
            break;
    }
}

(2)onDraw{
    if(mFraction> 0.3){

    }else{

    }
}

5.上述两种方式可以搭配工具类使用.会更好.

6.主要将动画分解,然后学会动画.
package com.example.administrator.animationworkdemo.views;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

/**
 * Created by SuperD on 2017/2/28.
 * Demo10中的View
 */

public class SearchAnimView2 extends View implements View.OnClickListener {
    private static final int LINE_WIDTH = 9;
    private static final int LINE_COLOR = Color.BLACK;
    private static final int DEFAULT_POINT_SIZE = 3;
    private static final int DEFAULT_DURATION = 3000;

    private Paint mPaint;
    private Paint mArcPaint;

    private boolean isDotShowing = true;

    //基本的数据参数
    private float mWidth;
    private float mHeight;
    private float mCenterX;
    private float mCenterY;
    //圆的半径
    private float mCircleRadius;
    //显示圆的范围
    private RectF mRectF;
    //整体的路径
    private Path mPath;
    //外圈的粘性部分
    private Path mArcPath;
    private PathMeasure mPathMeasure;
    private float mPathLength;
    private float mCurrentPos[] = new float[2];
    private float mCurrentTan[] = new float[2];

    private ValueAnimator mAnim;
    //当前动画播放的进度
    private float mFraction;


    public SearchAnimView2(Context context) {
        this(context, null);
    }

    public SearchAnimView2(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SearchAnimView2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }


    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //设置笔刷的图形样式,以下笔刷为圆形样式.
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(LINE_WIDTH);
        mPaint.setColor(LINE_COLOR);

        mArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mArcPaint.setStyle(Paint.Style.FILL);
        mArcPaint.setColor(Color.WHITE);

        mPath = new Path();
        mPathMeasure = new PathMeasure();
        mArcPath = new Path();

        mAnim = ValueAnimator.ofFloat(1f, 100f);
        mAnim.setDuration(DEFAULT_DURATION);
        mAnim.setInterpolator(new LinearInterpolator());
        mAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mFraction = animation.getAnimatedFraction();
                invalidate();
            }
        });
        setOnClickListener(this);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
        mCenterX = mWidth / 2;
        mCenterY = mHeight / 2;
        mCircleRadius = mWidth / 4;
        //绘制圆弧的范围
        mRectF = new RectF(
                mCenterX - 0.95f * mCircleRadius,
                mCenterY - 0.95f * mCircleRadius,
                mCenterX + 0.95f * mCircleRadius,
                mCenterY + 0.95f * mCircleRadius);
        //移动到圆柄的尾部
        mPath.moveTo(mCenterX + 2.2f * mCircleRadius / (float) Math.sqrt(2),
                mCenterY + 2.2f * mCircleRadius / (float) Math.sqrt(2));
        mPath.lineTo(mCenterX, mCenterY);
        //形成R 根号3 R 2R的直角三角形
        mPath.lineTo(mCenterX - 0.45f * mCircleRadius * (float) Math.sqrt(3),
                mCenterY + 0.45f * mCircleRadius);
        //取对称点
        mPath.lineTo(mCenterX - 0.45f * mCircleRadius * (float) Math.sqrt(3),
                mCenterY - 0.45f * mCircleRadius);
        mPath.lineTo(mCenterX + 0.45f * mCircleRadius * (float) Math.sqrt(3),
                mCenterY);
        //回到原点
        mPath.lineTo(mCenterX, mCenterY);
        mPath.lineTo(mCenterX + 2.2f * mCircleRadius / (float) Math.sqrt(2),
                mCenterY + 2.2f * mCircleRadius / (float) Math.sqrt(2));
        mPathMeasure.setPath(mPath, false);
        mPathLength = mPathMeasure.getLength();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        float sin45 = (float) Math.sin(Math.PI / 4);
        //通过mFraction来控制动画的时间阶段.
        if (mFraction <= 0.2) { //放大镜手柄收缩
            //在0.2f的路程内手柄从 1 到 0 消失成点
            canvas.drawCircle(mCenterX, mCenterY, mCircleRadius - mCircleRadius * mFraction, mPaint);
            canvas.drawLine(mCenterX + mCircleRadius * sin45 + 1.2f * mCircleRadius * sin45 * mFraction / 0.2f,
                    mCenterY + mCircleRadius * sin45 + 1.2f * mCircleRadius * sin45 * mFraction / 0.2f,
                    mCenterX + 2.2f * mCircleRadius * sin45,
                    mCenterY + 2.2f * mCircleRadius * sin45,
                    mPaint);
        } else if (mFraction <= 0.8) {
            //取 0.2f -0.6f的path的点
            mPathMeasure.getPosTan(0 + mPathLength * (mFraction - 0.2f) / 0.6f, mCurrentPos, mCurrentTan);
            //在圆心左右R/3处闪烁小球,形成闪烁效果.
            if (mCurrentPos[1] == mCenterY &&
                    mCurrentPos[0] <= mCenterX + mCircleRadius / 3 &&
                    mCurrentPos[0] >= mCenterX - mCircleRadius / 3) {
                if (isDotShowing) {
                    isDotShowing = false;
                } else {
                    //在轨迹中的小球
                    canvas.drawCircle(mCurrentPos[0], mCurrentPos[1], DEFAULT_POINT_SIZE, mPaint);
                    isDotShowing = true;
                }
            } else {
                canvas.drawCircle(mCurrentPos[0], mCurrentPos[1], DEFAULT_POINT_SIZE, mPaint);
            }
            //小球从外部回来的过程, 圆的半径需要回复圆状
            if (mFraction <= 0.3) {
                canvas.drawCircle(mCenterX, mCenterY,
                        0.8f * mCircleRadius + mCircleRadius * 2 * (mFraction - 0.2f), mPaint);
            } else {
                canvas.drawCircle(mCenterX, mCenterY, mCircleRadius, mPaint);
            }
            //就是一层白色的背景效果,在小球进入圆的时候做了一层效果
            if (mFraction <= 0.35 && mFraction > 0.3) {
                canvas.drawArc(mRectF, 45 - 55 * (mFraction - 0.3f) / 0.05f,
                        110 * (mFraction - 0.3f) / 0.05f, false, mArcPaint);
            } else if (mFraction <= 0.4 && mFraction > 0.35) {
                canvas.drawArc(mRectF, 45 - 55 / 0.05f * (0.4f - mFraction),
                        110 / 0.05f * (0.4f - mFraction), false, mArcPaint);
            }

            //外圈的粘性部分,在小球出去的时候 绘制一条弹力的贝塞尔曲线.
            if (mFraction <= 0.75 && mFraction > 0.7) {
                mArcPath.reset();
                mArcPath.moveTo(mCenterX + mCircleRadius, mCenterY);
                mArcPath.cubicTo(mCenterX + mCircleRadius + 8 * (mFraction - 0.7f) / 0.05f,
                        mCenterY + mCircleRadius / 2 + 8 * (mFraction - 0.7f) / 0.05f,
                        mCenterX + mCircleRadius / 2 + 8 * (mFraction - 0.7f) / 0.05f,
                        mCenterY + mCircleRadius + 8 * (mFraction - 0.7f) / 0.05f,
                        mCenterX,
                        mCenterY + mCircleRadius);
                canvas.drawPath(mArcPath, mPaint);
            } else if (mFraction <= 0.8 && mFraction > 0.75) {
                mArcPath.reset();
                mArcPath.moveTo(mCenterX + mCircleRadius, mCenterY);
                mArcPath.cubicTo(mCenterX + mCircleRadius + 8 * (0.8f - mFraction) / 0.05f,
                        mCenterY + mCircleRadius / 2 + 8 * (0.8f - mFraction) / 0.05f,
                        mCenterX + mCircleRadius / 2 + 8 * (0.8f - mFraction) / 0.05f,
                        mCenterY + mCircleRadius + 8 * (0.8f - mFraction) / 0.05f,
                        mCenterX,
                        mCenterY + mCircleRadius);
                canvas.drawPath(mArcPath, mPaint);
            }
        } else { //放大镜手柄伸长
            canvas.drawCircle(mCenterX, mCenterY, mCircleRadius, mPaint);
            canvas.drawLine(mCenterX + 2.2f * mCircleRadius * sin45 - 1.2f * mCircleRadius * sin45 * (mFraction - 0.8f) / 0.2f,
                    mCenterY + 2.2f * mCircleRadius * sin45 - 1.2f * mCircleRadius * sin45 * (mFraction - 0.8f) / 0.2f,
                    mCenterX + 2.2f * mCircleRadius * sin45,
                    mCenterY + 2.2f * mCircleRadius * sin45
                    , mPaint);
        }


    }

    @Override
    public void onClick(View v) {
        if (!mAnim.isRunning()) {
            mAnim.start();
        }
    }
}

你可能感兴趣的:(Android动画之旅,Android动画之旅)