aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/views/RippleCanvas.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/views/RippleCanvas.kt')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/RippleCanvas.kt83
1 files changed, 83 insertions, 0 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/RippleCanvas.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/RippleCanvas.kt
new file mode 100644
index 00000000..719a01cc
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/RippleCanvas.kt
@@ -0,0 +1,83 @@
+package com.pitchedapps.frost.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) {
+ val paint: Paint = Paint()
+ var baseColor = Color.TRANSPARENT
+ 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
+ }
+ }
+ }
+
+ @JvmOverloads 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.setRadius(animation.animatedValue as Float)
+ invalidate()
+ }
+ animator.start()
+ }
+
+ fun set(color: Int) {
+ baseColor = color
+ ripples.clear()
+ invalidate()
+ }
+
+ inner class Ripple internal constructor(val color: Int, val x: Float, val y: Float, var radius: Float, val maxRadius: Float) {
+ internal fun setRadius(r: Float) {
+ radius = r
+ }
+ }
+
+ companion object {
+ val MIDDLE = -1.0f
+ }
+}