Android Canvas动画实践:实现小球旋转、扩散、聚合效果

引言

在Android开发中,Canvas为我们提供了一个强大的绘图工具。本文通过分析一个自定义View组件SplashView,展示如何利用Canvas实现‌小球旋转‌、‌扩散聚合‌和‌水波纹‌动画效果,并搭配关键代码片段解释实现细节。

一、效果演示

以下是动画的连贯流程:

旋转阶段‌:多个彩色小球围绕中心旋转。
扩散聚合‌:小球向外扩散后聚拢。
水波纹‌:中心出现逐渐扩大的透明圆洞,背景颜色变化。

二、小球旋转动画

旋转动画通过不断改变小球的绘制角度实现。以下是核心代码:

private class RotateState extends SplashState {
        private RotateState() {
            mValueAnimator = ValueAnimator.ofFloat(0, (float) (Math.PI * 2));
            mValueAnimator.setRepeatCount(2);
            mValueAnimator.setDuration(mRotateDuration);
            mValueAnimator.setInterpolator(new LinearInterpolator());
            mValueAnimator.addUpdateListener(animation -> {
                mCurrentRotateAngle = (float) animation.getAnimatedValue();
                invalidate();
            });
            mValueAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    mState = new MergeState();
                }
            });
            mValueAnimator.start();
        }

        @Override
        void drawState(Canvas canvas) {
            //绘制背景
            drawBackground(canvas);
            //绘制6个小球
            drawCircles(canvas);
        }
    }


关键点‌:

通过三角函数(Math.cos和Math.sin)计算每个小球的位置。


三、扩散聚合动画

扩散聚合效果通过动态改变旋转半径实现,使用ValueAnimator驱动动画:

// 扩散聚合状态(MergeState类)
private class MergeState extends SplashState {
    private ValueAnimator mExpandAnimator;

    public MergeState() {
        // 创建扩散动画(半径从小变大)
        mExpandAnimator = ValueAnimator.ofFloat(mCircleRadius, mRotateRadius);
        mExpandAnimator.setDuration(mRotateDuration);
        mExpandAnimator.addUpdateListener(animation -> {
            mCurrentRotateRadius = (float) animation.getAnimatedValue();
            invalidate();
        });
        // 动画结束后反向播放(聚合效果)
        mExpandAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mExpandAnimator.reverse();
            }
        });
        mExpandAnimator.start();
    }

    @Override
    public void drawState(Canvas canvas) {
        drawBackground(canvas);
        drawCircles(canvas, mCurrentRotateAngle, mCurrentRotateRadius);
    }
}


关键点‌:

ValueAnimator驱动半径从初始值到目标值的变化。
通过reverse()实现反向动画,形成“扩散-聚合”循环。


四、水波纹动画

水波纹效果通过绘制逐渐扩大的“空洞”实现,结合背景颜色变化:

// 水波纹状态(ExpandState类)
private class ExpandState extends SplashState {
    private ValueAnimator mHoleAnimator;

    public ExpandState() {
        mHoleAnimator = ValueAnimator.ofFloat(0, mDistance);
        mHoleAnimator.setDuration(mRotateDuration);
        mHoleAnimator.addUpdateListener(animation -> {
            mCurrentHoleRadius = (float) animation.getAnimatedValue();
            invalidate();
        });
        mHoleAnimator.start();
    }

    @Override
    public void drawState(Canvas canvas) {
        drawBackground(canvas);
    }
}
// 绘制背景(带空洞)
    private void drawBackground(Canvas canvas) {
        if (mCurrentHoleRadius > 0) {
            float strokeWidth = mDistance - mCurrentHoleRadius;
            float radius = strokeWidth / 2 + mCurrentHoleRadius;
            mHolePaint.setStrokeWidth(strokeWidth);
            canvas.drawCircle(mCenterX, mCenterY, radius, mHolePaint);
        } else {
            canvas.drawColor(mBackgroundColor);
        }
    }


四、动画状态切换

通过状态模式管理不同动画阶段:

// 抽象状态类
private abstract class SplashState {
    public abstract void drawState(Canvas canvas);
}

// 动画结束后的状态切换逻辑
mExpandAnimator.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        mSplashState = new ExpandState(); // 切换到水波纹状态
    }
});


五、总结

通过Canvas和属性动画的配合,我们实现了三种连贯的动画效果:

小球旋转‌:基于角度动态计算位置。
扩散聚合‌:通过ValueAnimator驱动半径变化。
水波纹‌:逐渐扩大圆圈,露出原本底色。

完整代码已托管至Gitcode:GitCode - 全球开发者的开源社区,开源代码托管平台
希望本文能为你实现复杂Canvas动画提供启发!

通过代码片段与文字的结合,读者可以更直观地理解每个动画的实现方式。如果需要进一步解释某个代码细节,可以随时补充!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值