Android 自定义水波纹扩散控件【kotlin】

Android 自定义水波纹扩散控件【kotlin】

效果图:圆从中心开始扩散,在扩散过程中逐渐透明。
在这里插入图片描述
实现思路:使用多个属性动画去控制。
代码实现:

package com.fht.kotlin.widget

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.os.Handler
import android.util.AttributeSet
import android.view.View

/**
 * @author fenghaitao
 * @time 2021/11/4 15:35
 * 水波纹扩散控件
 */
class RippleView @JvmOverloads constructor(
        context: Context, attributeSet: AttributeSet, defStyleAttr: Int = 0
) :
        View(context, attributeSet, defStyleAttr) {
    private val circlePaint = Paint()
    private var mCountCircle = 6 //圆的数量
    private var mRadius = ArrayList<Float>()
    private var mAlphas = ArrayList<Int>()
    private var mColorStart = 0
    private var mColorEnd = 0
    private var index = 0
    private var valueAnimators = ArrayList<ValueAnimator>()
    private var mSpeed = 500L
    private var mDuration = 3000L

    init {
        mColorStart = Color.GREEN
        mColorEnd = Color.BLUE
        circlePaint.color = mColorStart
        circlePaint.isAntiAlias = false
        circlePaint.style = Paint.Style.FILL
        mRadius.add(0f)
        mAlphas.add(255)
    }

    @SuppressLint("DrawAllocation")
    override fun layout(l: Int, t: Int, r: Int, b: Int) {
        super.layout(l, t, r, b)
        //设置阴影
        circlePaint.shader = LinearGradient(
                l.toFloat(), b / 2f, r.toFloat(), b / 2f,
                intArrayOf(mColorStart, mColorEnd), null, Shader.TileMode.CLAMP
        )
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if (canvas != null) {
            for (i in 0..mRadius.size - 1) {
                circlePaint.alpha = mAlphas[i]
                canvas.drawCircle(width / 2f, height / 2f, mRadius[i], circlePaint)
            }
        }
    }

    private fun createRippleAnimator(index: Int): ValueAnimator {
        return ValueAnimator.ofFloat(0f, 1f).apply {
            duration = mDuration
            repeatCount = ValueAnimator.INFINITE
            addUpdateListener {
                mAlphas[index] = (255 * (1 - (it.animatedValue as Float))).toInt()
                mRadius[index] = width / 2f * it.animatedValue as Float
                invalidate()
            }
        }
    }

    private fun start() {
        val handler = Handler()
        handler.postDelayed(object : Runnable {
            override fun run() {
                if (index >= mCountCircle) {
                    return
                }
                mAlphas.add(255)
                mRadius.add(0f)
                val animator = createRippleAnimator(index)
                animator.start()
                valueAnimators.add(animator)
                index++
                handler.postDelayed(this, mSpeed)
            }
        }, mSpeed)
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        startAnimator()
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        stopAnimator()
    }

    /**
     * 开始动画
     */
    fun startAnimator() {
        if (index != 0) {
            return
        }
        start()
    }

    /**
     * 停止所有动画
     */
    fun stopAnimator() {
        index = 0
        for (valueAnimator: ValueAnimator in valueAnimators) {
            valueAnimator.cancel()
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值