Android加载动画系列—— GhostLoadingAnim

Android加载动画系列——GhostLoadingAnim

有时候,我们玩一些冒险类的游戏,场景加载的时候会出现一个来回游荡的幽灵,今天就让我们来看看这个效果是怎么实现的吧~

让我们先来看看效果图:


1、GhostLoadingAnim.java源码如下:
public class GhostLoadingAnim extends View {

    private Paint mPaint, mPaintHand, mPaintShadow, mPaintArms;
    private float mWidth = 0f;
    private float mHeight = 0f;
    private RectF rectFGhost = new RectF();
    private RectF rectFGhostShadow = new RectF();
    private float mPadding = 0f;
    int mskirtH = 0;
    private Path path = new Path();

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

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

    public GhostLoadingAnim(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        mPadding = 10;
        mskirtH = (int) (mWidth / 40);
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.WHITE);

        mPaintHand = new Paint();
        mPaintHand.setAntiAlias(true);
        mPaintHand.setStyle(Paint.Style.FILL);
        mPaintHand.setColor(Color.argb(220, 0, 0, 0));

        mPaintShadow = new Paint();
        mPaintShadow.setAntiAlias(true);
        mPaintShadow.setStyle(Paint.Style.FILL);
        mPaintShadow.setColor(Color.argb(60, 0, 0, 0));

        mPaintArms = new Paint();
        mPaintArms.setAntiAlias(true);
        mPaintArms.setStyle(Paint.Style.FILL);
        mPaintArms.setStrokeWidth(8);
        mPaintArms.setColor(Color.argb(150, 0, 0, 0));
    }

    private ValueAnimator valueAnimator;
    private float mAnimatedValue = 0.f;
    int onAnimationRepeatFlag = 1;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        float distance = (mWidth - 2 * mPadding) / 3 * 2 * mAnimatedValue;
        rectFGhost.left = mPadding + distance;
        rectFGhost.right = (mWidth - 2 * mPadding) / 3 + distance;
        float moveY = 0f;
        float moveYMax = mHeight / 4f / 2f;
        float shadowHighMax = 5f;
        float shadowHigh = 0f;

        if (mAnimatedValue <= 0.25) {
            moveY = (float) (moveYMax / 0.25 * mAnimatedValue);
            rectFGhost.top = moveY;
            rectFGhost.bottom = mHeight / 4 * 3 + moveY;
            shadowHigh = shadowHighMax / 0.25f * mAnimatedValue;
        } else if (mAnimatedValue > 0.25 && mAnimatedValue <= 0.5f) {
            moveY = (float) (moveYMax / 0.25f * (mAnimatedValue - 0.25f));
            rectFGhost.top = moveYMax - moveY;
            rectFGhost.bottom = mHeight / 4 * 3 + moveYMax - moveY;
            shadowHigh = shadowHighMax - shadowHighMax / 0.25f * (mAnimatedValue - 0.25f);
        } else if (mAnimatedValue > 0.5 && mAnimatedValue <= 0.75f) {
            moveY = (float) (moveYMax / 0.25 * (mAnimatedValue - 0.5f));
            rectFGhost.top = moveY;
            rectFGhost.bottom = mHeight / 4 * 3 + moveY;
            shadowHigh = shadowHighMax / 0.25f * (mAnimatedValue - 0.5f);
        } else if (mAnimatedValue > 0.75 && mAnimatedValue <= 1f) {
            moveY = (float) (moveYMax / 0.25 * (mAnimatedValue - 0.75f));
            rectFGhost.top = moveYMax - moveY;
            rectFGhost.bottom = mHeight / 4 * 3 + moveYMax - moveY;
            shadowHigh = shadowHighMax - shadowHighMax / 0.25f * (mAnimatedValue - 0.75f);
        }

        rectFGhostShadow.top = mHeight - 25 + shadowHigh;
        rectFGhostShadow.bottom = mHeight - 5 - shadowHigh;
        rectFGhostShadow.left = rectFGhost.left + 5 + shadowHigh * 3;
        rectFGhostShadow.right = rectFGhost.right - 5 - shadowHigh * 3;
        drawShadow(canvas);
        drawHead(canvas);
        drawBody(canvas);
        drawHand(canvas);
        canvas.restore();
    }

    private void drawShadow(Canvas canvas) {
        canvas.drawArc(rectFGhostShadow, 0, 360, false, mPaintShadow);
    }

    private void drawHead(Canvas canvas) {
        canvas.drawCircle(rectFGhost.left + rectFGhost.width() / 2,
                rectFGhost.width() / 2 + rectFGhost.top,
                rectFGhost.width() / 2 - 15,
                mPaint);
    }

    private void drawHand(Canvas canvas) {
        canvas.drawCircle(rectFGhost.left + rectFGhost.width() / 2 - mskirtH * 3 / 2 + mskirtH * onAnimationRepeatFlag,
                rectFGhost.width() / 2 + mskirtH + rectFGhost.top,
                mskirtH * 0.9f, mPaintHand);
        canvas.drawCircle(rectFGhost.left + rectFGhost.width() / 2 + mskirtH * 3 / 2 + mskirtH * onAnimationRepeatFlag,
                rectFGhost.width() / 2 + mskirtH + rectFGhost.top, mskirtH * 0.9f, mPaintHand);
    }

    float wspace = 10f;
    float hspace = 10f;

    private void drawBody(Canvas canvas) {
        path.reset();

        float x = (float) ((rectFGhost.width() / 2 - 15) * Math.cos(5 * Math.PI / 180f));
        float y = (float) ((rectFGhost.width() / 2 - 15) * Math.sin(5 * Math.PI / 180f));
        float x2 = (float) ((rectFGhost.width() / 2 - 15) * Math.cos(175 * Math.PI / 180f));
        float y2 = (float) ((rectFGhost.width() / 2 - 15) * Math.sin(175 * Math.PI / 180f));

        path.moveTo(rectFGhost.left + rectFGhost.width() / 2 - x, rectFGhost.width() / 2 - y + rectFGhost.top);
        path.lineTo(rectFGhost.left + rectFGhost.width() / 2 - x2, rectFGhost.width() / 2 - y2 + rectFGhost.top);
        path.quadTo(rectFGhost.right + wspace / 2, rectFGhost.bottom, rectFGhost.right - wspace, rectFGhost.bottom - hspace);

        float a = mskirtH;
        float m = (rectFGhost.width() - 2 * wspace) / 7f;

        for (int i = 0; i < 7; i++) {
            if (i % 2 == 0) {
                path.quadTo(rectFGhost.right - wspace - m * i - (m / 2), rectFGhost.bottom - hspace - a, rectFGhost.right - wspace - (m * (i + 1)), rectFGhost.bottom - hspace);

            } else {
                path.quadTo(rectFGhost.right - wspace - m * i - (m / 2), rectFGhost.bottom - hspace + a, rectFGhost.right - wspace - (m * (i + 1)), rectFGhost.bottom - hspace);
            }
        }

        path.quadTo(rectFGhost.left - 5, rectFGhost.bottom, rectFGhost.left + rectFGhost.width() / 2 - x, rectFGhost.width() / 2 - y + rectFGhost.top);
        path.close();
        canvas.drawPath(path, mPaint);
    }

    private ValueAnimator startViewAnim(float startF, float endF, long time) {
        valueAnimator = ValueAnimator.ofFloat(startF, endF);
        valueAnimator.setDuration(time);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.setRepeatMode(ValueAnimator.RESTART);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mAnimatedValue = (float) valueAnimator.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationRepeat(Animator animation) {
                super.onAnimationRepeat(animation);
                onAnimationRepeatFlag = onAnimationRepeatFlag * -1;
                if (onAnimationRepeatFlag == -1) {
                    wspace = 22;
                } else {
                    wspace = -2;
                }
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
            }

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
            }
        });
        if (!valueAnimator.isRunning()) {
            wspace = -1;
            valueAnimator.start();
        }
        return valueAnimator;
    }

    public void stopAnim() {
        if (valueAnimator != null) {
            clearAnimation();
            valueAnimator.setRepeatCount(0);
            valueAnimator.cancel();
            valueAnimator.end();
            mAnimatedValue = 0f;
            wspace = 10;
            onAnimationRepeatFlag = 1;
            postInvalidate();
        }
    }

    public void startAnim() {
        stopAnim();
        startViewAnim(0f, 1f, 2500);
    }
}
 

2、接着在layout布局文件中使用我们自定义的动画控件

<com.cyril.loadinganim.GhostLoadingAnim
    android:id="@+id/ghostloadinganim"
    android:layout_width="200dp"
    android:layout_height="120dp"
     />
  

3、然后在Activity中实现动画的播放和停止,使用事例如下:

 
ghostLoadingAnim = (GhostLoadingAnim) findViewById(R.id.ghostloadinganim);
ghostLoadingAnim.startAnim();
 

4、  戳这里,小编带你去源码的下载地址:http://download.csdn.net/detail/zhimingshangyan/9582830

 

猜你喜欢

转载自blog.csdn.net/zhimingshangyan/article/details/52074705
今日推荐