diff options
Diffstat (limited to 'library/src/main/kotlin/ca/allanwang/kau/views/RippleCanvas.kt')
-rw-r--r-- | library/src/main/kotlin/ca/allanwang/kau/views/RippleCanvas.kt | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/library/src/main/kotlin/ca/allanwang/kau/views/RippleCanvas.kt b/library/src/main/kotlin/ca/allanwang/kau/views/RippleCanvas.kt new file mode 100644 index 0000000..2c44197 --- /dev/null +++ b/library/src/main/kotlin/ca/allanwang/kau/views/RippleCanvas.kt @@ -0,0 +1,79 @@ +package ca.allanwang.kau.views + +import android.animation.ValueAnimator +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.util.AttributeSet +import android.view.View + +/** + * Created by Allan Wang on 2016-11-17. + * + * + * Canvas drawn ripples that keep the previous color + * Extends to view dimensions + * Supports multiple ripples from varying locations + */ +class RippleCanvas @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : View(context, attrs, defStyleAttr) { + private val paint: Paint = Paint() + private var baseColor = Color.TRANSPARENT + private val ripples: MutableList<Ripple> = mutableListOf() + + init { + paint.isAntiAlias = true + paint.style = Paint.Style.FILL + } + + override fun onDraw(canvas: Canvas) { + canvas.drawColor(baseColor) + val itr = ripples.iterator() + while (itr.hasNext()) { + val r = itr.next() + paint.color = r.color + canvas.drawCircle(r.x, r.y, r.radius, paint) + if (r.radius == r.maxRadius) { + itr.remove() + baseColor = r.color + } + } + } + + fun ripple(color: Int, startX: Float = 0f, startY: Float = 0f, duration: Int = 1000) { + var x = startX + var y = startY + val w = width.toFloat() + val h = height.toFloat() + if (x == MIDDLE) + x = w / 2 + else if (x > w) x = 0f + if (y == MIDDLE) + y = h / 2 + else if (y > h) y = 0f + val maxRadius = Math.hypot(Math.max(x, w - x).toDouble(), Math.max(y, h - y).toDouble()).toFloat() + val ripple = Ripple(color, x, y, 0f, maxRadius) + ripples.add(ripple) + val animator = ValueAnimator.ofFloat(0f, maxRadius) + animator.duration = duration.toLong() + animator.addUpdateListener { animation -> + ripple.radius = animation.animatedValue as Float + invalidate() + } + animator.start() + } + + fun set(color: Int) { + baseColor = color + ripples.clear() + invalidate() + } + + internal class Ripple(val color: Int, val x: Float, val y: Float, var radius: Float, val maxRadius: Float) + + companion object { + const val MIDDLE = -1.0f + } +} |