自定义清理动画

先上图:
image

再附上:源码地址
欢迎大家star~

上面的自定义动画效果,有以下三个关键点:
1,背景颜色变化;
2,中心位置风车的旋转;
3,四周小圈圈,吸收进中心位置;
下面详细介绍它们实现方式:

实际整体控制动画的流畅性,是利用属性动画辅助的:

mAnim = ValueAnimator.ofInt(0, 100);
mAnim.setDuration(30 * 1000);
mAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float progress = animation.getAnimatedFraction();
        // ...省略代码
        invalidate();
    }
});

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int centerX = getWidth() / 2;
    int centerY = getHeight() / 2;

    // 背景色渐变
    // ...省略代码

    // 风扇 旋转
    // ...省略代码

    // 冲击的 圈圈
    // ...省略代码

    // 底部文案
    // ...省略代码
}

利用属性动画,在 onAnimationUpdate 监听里面,invalidate 重走 onDraw 重绘;

背景色变化
mAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float progress = animation.getAnimatedFraction();
        // ...省略代码
        mCurrentScore = (int) ((mTargetScore - mCurrentScore) * progress + mCurrentScore);
        mBgColor = mArgbEvaluator.evaluate((float) mCurrentScore/100, CleanColorHelper.Colors.RED, CleanColorHelper.Colors.GREEN);

        invalidate();
    }
});

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int centerX = getWidth() / 2;
    int centerY = getHeight() / 2;

    // 背景色
    canvas.drawColor(mBgColor);
    // 背景色上盖一层 渐变
    if (mLGradient == null) {
        mLGradient = new LinearGradient(0, 0, getWidth(), getHeight(), 0x88ffffff, 0x00ffffff, Shader.TileMode.REPEAT);
    }
    mPaint.setShader(mLGradient);
    canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);

    // 风扇 旋转
    // ...省略代码

    // 冲击的 圈圈
    // ...省略代码

    // 底部文案
    // ...省略代码
}
风车旋转
// ...省略代码
mScanBitmap = BitmapUtils.getBitmapFromResourceWithHighQuality(getContext().getResources(), R.drawable.manage_icon_scan_fs, 268, 268);
mAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float progress = animation.getAnimatedFraction();
        // ...省略代码
        // 每次旋转15度
        mScanAngle += 15;

        invalidate();
    }
});

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int centerX = getWidth() / 2;
    int centerY = getHeight() / 2;

    // 背景色
    // ...省略代码

    // 风扇 旋转
    if (mScanBitmap != null) {
        mPaint.setShader(null);
        mPaint.setAlpha((int) (255));
        mPaint.setStyle(Paint.Style.FILL);
        float scanAngle = mScanAngle % 360;
        int centerBmX = mScanBitmap.getWidth() / 2;
        int centerBmY = mScanBitmap.getHeight() / 2;
        // 把风车图片移到中心
        mBmMatrix.setTranslate(centerX - centerBmX, centerY - centerBmY);
        // 以图片中心,旋转角度
        mBmMatrix.preRotate(scanAngle, centerBmX, centerBmY);
        canvas.drawBitmap(mScanBitmap, mBmMatrix, mPaint);
    }

    // 冲击的 圈圈
    // ...省略代码

    // 底部文案
    // ...省略代码
}
冲击的圈圈
// 随机生成某个方向的 圈圈
private ScoreAnimationView.Circle obtainNewCircle(int where) {
    ScoreAnimationView.Circle circle = new ScoreAnimationView.Circle();
    circle.where = where;
    int random = DensityUtils.dip2px(-30f) + RandomUtils.getRandomInt(DensityUtils.dip2px(60f));
    if (where == 0) {
        circle.x = DensityUtils.dip2px(-100f) + random * 2;
        circle.y = DensityUtils.dip2px(-150f) + random;
        circle.radius = DensityUtils.dip2px(30f) + random / 6;
        circle.color = ScoreAnimationView.MC;
    } else if (where == 1) {
        circle.x = DensityUtils.dip2px(120f) + random;
        circle.y = DensityUtils.dip2px(-150f) + random / 2;
        circle.radius = DensityUtils.dip2px(25f) + random / 6;
        circle.color = ScoreAnimationView.MC;
    } else if (where == 2) {
        circle.x = DensityUtils.dip2px(-110f) + random;
        circle.y = DensityUtils.dip2px(150f) + random * 2;
        circle.radius = DensityUtils.dip2px(26f) + random / 6;
        circle.color = ScoreAnimationView.MC;
    } else if (where == 3) {
        circle.x = DensityUtils.dip2px(100f) + random / 2;
        circle.y = DensityUtils.dip2px(150f) + random;
        circle.radius = DensityUtils.dip2px(20f) + random / 6;
        circle.color = ScoreAnimationView.MC;
    } else if (where == 4) {
        circle.x = DensityUtils.dip2px(-200f) + random / 2;
        circle.y = DensityUtils.dip2px(10f) + random / 2;
        circle.radius = DensityUtils.dip2px(15f) + random / 6;
        circle.color = ScoreAnimationView.MC;
    } else if (where == 5) {
        circle.x = DensityUtils.dip2px(200f) + random / 2;
        circle.y = DensityUtils.dip2px(-10f) + random / 2;
        circle.radius = DensityUtils.dip2px(18f) + random / 6;
        circle.color = ScoreAnimationView.MC;
    }
    return circle;
}
/**
 * 添加新的一组圈圈,到屏幕里;
 * mCurrentNextTime 会逐渐变大的,每间隔 NEXT_NEW_TIME 的时间,会增加一组圈圈,显得看着连贯冲击感;
 */
private void addNewCircles() {
    if (mCurrentNextTime >= NEXT_NEW_TIME
            && mCurrentNextTime < NEXT_NEW_TIME + LOOP_TIME) {
        mCurrentNextTime = 0;
        mCircles.add(obtainNewCircle(0));
        mCircles.add(obtainNewCircle(1));
        mCircles.add(obtainNewCircle(2));
        mCircles.add(obtainNewCircle(3));
        mCircles.add(obtainNewCircle(4));
        mCircles.add(obtainNewCircle(5));
    }
}
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int centerX = getWidth() / 2;
    int centerY = getHeight() / 2;

    // 背景色
    // ...省略代码

    // 风扇 旋转
    // ...省略代码

    // 冲击的 圈圈
    Iterator<ScoreAnimationView.Circle> it = mCircles.iterator();
    while (it.hasNext()) {
        ScoreAnimationView.Circle circle = it.next();
        // 每个圈圈都有自己的进度,大于1了,就可以回收删除了;
        if (circle.progress > 1) {
            it.remove();
        } else {
            mPaint.setShader(null);
            mPaint.setColor(circle.color);
            mPaint.setAlpha((int) (125 * (1f - circle.progress)));
            float x = centerX + circle.x * (1f - circle.progress);
            float y = centerY + circle.y * (1f - circle.progress);
            float radius = circle.radius * (1.2f - circle.progress);
            canvas.drawCircle(x, y, radius, mPaint);
            circle.progress += LOOP_TIME;
        }
    }
    addNewCircles();
    mCurrentNextTime += LOOP_TIME;

    // 底部文案
    // ...省略代码
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章