class RippleDrawable : Drawable() {
private val interpolator: Interpolator = AccelerateInterpolator()
private var mPaint: Paint = Paint()
private var mRadius: Float = 0.0f
private var mWidth: Float = 0.0f
private var mHeight: Float = 0.0f
private var mMaxRadius: Float = 0.0f
/**
* 点击的锚点 x值
*/
private var mPivotX: Float = 0.0f
/**
* 点击的锚点 y值
*/
private var mPivotY: Float = 0.0f
private var mMotionX: Float = 0.0f
private var mMotionY: Float = 0.0f
private var mProgress = 0.0f
private var mAlpha = 255
/**
* 多久执行runable一次 也就是多久刷新一次
*/
private var delayTime: Long = 2L
/**
* 递减透明度值
*/
private var desAlpha = 2
init {
mPaint.isAntiAlias = true
mPaint.isDither = true
mPaint.color = Color.CYAN
mPaint.style = Paint.Style.FILL
}
//绘制圆形
override fun draw(canvas: Canvas) {
canvas.drawCircle(mPivotX, mPivotY, mRadius, mPaint)
}
override fun onBoundsChange(bounds: Rect) {
super.onBoundsChange(bounds)
mWidth = bounds.width().toFloat()
mHeight = bounds.height().toFloat()
mMaxRadius = min(mWidth, mHeight)
}
override fun setAlpha(alpha: Int) {
mPaint.alpha = alpha
}
override fun setColorFilter(colorFilter: ColorFilter?) {
mPaint.colorFilter = colorFilter
}
override fun getOpacity(): Int {
return PixelFormat.OPAQUE;
}
fun onTouchEvent(event: MotionEvent) {
when (event.actionMasked) {
MotionEvent.ACTION_DOWN -> {
onTouchDown(event)
}
MotionEvent.ACTION_MOVE -> {
onTouchMove(event)
}
MotionEvent.ACTION_UP -> {
onTouchUp(event)
}
}
}
private fun onTouchUp(event: MotionEvent) {
}
private fun onTouchMove(event: MotionEvent) {
}
private fun onTouchDown(event: MotionEvent) {
mMotionX = event.x
mMotionY = event.y
mRadius = 0f
mProgress = 0.0f
mAlpha = 255
alpha = mAlpha
unscheduleSelf(mEnterRunnable)
scheduleSelf(mEnterRunnable, SystemClock.uptimeMillis() + delayTime)
}
private val mExitRunnable: Runnable = object : Runnable {
override fun run() {
val alpha = mAlpha - desAlpha
if (alpha > 0) {
//从不透明变成完全透明实现Drawable内容不可见
mAlpha = alpha
setAlpha(alpha)
invalidateSelf()
scheduleSelf(this, SystemClock.uptimeMillis() + delayTime)
} else {
mAlpha = 0
setAlpha(mAlpha)
invalidateSelf()
}
}
}
private val mEnterRunnable: Runnable = object : Runnable {
override fun run() {
//进度大于等于1了,那么就执行退出动画
if (mProgress >= 1.0f) {
unscheduleSelf(this)
scheduleSelf(mExitRunnable, SystemClock.uptimeMillis() + delayTime)
}
//不断增大圆形半径
mProgress += 0.02f
mRadius = mMaxRadius * interpolator.getInterpolation(mProgress)
mPivotX = mMotionX
mPivotY = mMotionY
invalidateSelf()
scheduleSelf(this, SystemClock.uptimeMillis() + delayTime)
}
}
}
包含了涟漪效果Drawable的Button。
class RippleButton @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : AppCompatButton(context, attrs, defStyleAttr), Drawable.Callback {
private val mDrawable: RippleDrawable = RippleDrawable()
init {
mDrawable.callback = this
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
mDrawable.setBounds(0, 0, width, height)
}
override fun onDraw(canvas: Canvas) {
mDrawable.draw(canvas)
super.onDraw(canvas)
}
override fun verifyDrawable(who: Drawable): Boolean {
return mDrawable == who || super.verifyDrawable(who)
}
override fun onTouchEvent(event: MotionEvent): Boolean {
mDrawable.onTouchEvent(event)
super.onTouchEvent(event)
return true
}
}
RippleDrawable内部onBoundsChange会在View的onSizeChange发生回调,会记录当前Drawable展示的宽高和圆形的最大半径,在draw方法中会根据圆心和半径绘制圆形,内部的mEnterRunnable表示用户按下时执行的圆形不断变大动画,mExitRunnable表示变大动画执行完成后圆形从不透明到全透明最后消失的动画。
效果视频上传不了,可以跑代码看下效果。