花里胡哨切换背景色

说明:
很多情况会有切换背景或者主题的需求。

看一下这个效果:
(图片)

思路:
1.肯定需要绘制一个圆,圆的直径需要覆盖整个手机屏幕

2.圆在绘制过程中需要加载至布局之中,且位于背景色和按钮之间,否则无法看到渐变效果

3.绘制成功后,修改根布局背景色,移除绘制的圆,完成切换过程

实现:
方式1.绘制圆的过程中,可以使用postDelayed每延迟一段时间,刷新onDraw进行绘制,产生动画的感觉

private fun drawCicle(canvas: Canvas?, circleX: Float, circleY: Float) {
        if (mRaduis > mMaxRaduis) {
            fiexdBgColor(canvas)
            this.isStartDraw = false
            mListener.endCallBack()
            return
        }
        canvas?.drawCircle(circleX, circleY, mRaduis, mPaint)
        postDelayed(Runnable { mRaduis += 30; invalidate() }, 5)
    }

方式2.直接使用值动画,将圆的半径设置为屏幕尺寸,在onAnimationUpdate回调函数中刷新onDraw进行绘制,使用动画的好处是可以很方便的控制时间,并且能使用插值器

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        this.mMaxRaduis = sqrt(w.toDouble().pow(2.0) + h.toDouble().pow(2.0)).toFloat()
        valueAnimator = ValueAnimator.ofFloat(0F, mMaxRaduis)
        valueAnimator.duration = 500
        valueAnimator.addUpdateListener { animation ->
            run {
                mRaduis = animation.animatedValue as Float
                postInvalidate()
            }
        }
        valueAnimator.addListener(object : Animator.AnimatorListener {
            override fun onAnimationRepeat(animation: Animator?) {
            }

            override fun onAnimationEnd(animation: Animator?) {
                isStartDraw = false
                mListener.endCallBack()
            }

            override fun onAnimationCancel(animation: Animator?) {
            }

            override fun onAnimationStart(animation: Animator?) {
            }

        })

        valueAnimator.start()
    }

细节部分
根布局移除圆View的时候,需要使用post,否则会可能出现异常:
“java.lang.NullPointerException: Attempt to read from field ‘int android.view.View.mViewFlags’ on a null object reference”
这是因为在快速点击按钮的时候,parentView一边在addView一边在removeView,使得管理混乱。

这里可以添加一把锁,正在添加的时候,禁止继续添加,保证切换动画中,始终保持只有一个View正在执行。
源码戳这里:WaveCircleView