aboutsummaryrefslogtreecommitdiff
path: root/library/src/main/kotlin/ca/allanwang/kau/views/RippleCanvas.kt
diff options
context:
space:
mode:
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.kt79
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
+ }
+}