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.kt140
1 files changed, 0 insertions, 140 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
deleted file mode 100644
index 805fb21..0000000
--- a/library/src/main/kotlin/ca/allanwang/kau/views/RippleCanvas.kt
+++ /dev/null
@@ -1,140 +0,0 @@
-package ca.allanwang.kau.views
-
-import android.animation.ArgbEvaluator
-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
-import ca.allanwang.kau.utils.adjustAlpha
-
-/**
- * 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
- }
-
- /**
- * Drawing the ripples involves having access to the next layer if it exists,
- * and using its values to decide on the current color.
- * If the next layer requests a fade, we will adjust the alpha of our current layer before drawing.
- * Otherwise we will just draw the color as intended
- */
- override fun onDraw(canvas: Canvas) {
- val itr = ripples.listIterator()
- if (!itr.hasNext()) return canvas.drawColor(baseColor)
- var next = itr.next()
- canvas.drawColor(colorToDraw(baseColor, next.fade, next.radius, next.maxRadius))
- var last = false
- while (!last) {
- val current = next
- if (itr.hasNext()) next = itr.next()
- else last = true
- //We may fade any layer except for the last one
- paint.color = colorToDraw(current.color, next.fade && !last, next.radius, next.maxRadius)
- canvas.drawCircle(current.x, current.y, current.radius, paint)
- if (current.radius == current.maxRadius) {
- if (!last) {
- itr.previous()
- itr.remove()
- itr.next()
- } else {
- itr.remove()
- }
- baseColor = current.color
- }
- }
- }
-
- /**
- * Given our current color and next layer's radius & max,
- * we will decide on the alpha of our current layer
- */
- internal fun colorToDraw(color: Int, fade: Boolean, current: Float, goal: Float): Int {
- if (!fade || (current / goal <= FADE_PIVOT)) return color
- val factor = (goal - current) / (goal - FADE_PIVOT * goal)
- return color.adjustAlpha(factor)
- }
-
- /**
- * Creates a ripple effect from the given starting values
- * [fade] will gradually transition previous ripples to a transparent color so the resulting background is what we want
- * this is typically only necessary if the ripple color has transparency
- */
- fun ripple(color: Int, startX: Float = 0f, startY: Float = 0f, duration: Long = 600L, fade: Boolean = Color.alpha(color) != 255) {
- val w = width.toFloat()
- val h = height.toFloat()
- val x = when (startX) {
- MIDDLE -> w / 2
- END -> w
- else -> startX
- }
- val y = when (startY) {
- MIDDLE -> h / 2
- END -> h
- else -> startY
- }
- 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, fade)
- ripples.add(ripple)
- val animator = ValueAnimator.ofFloat(0f, maxRadius)
- animator.duration = duration
- animator.addUpdateListener { animation ->
- ripple.radius = animation.animatedValue as Float
- invalidate()
- }
- animator.start()
- }
-
- /**
- * Sets a color directly; clears ripple queue if it exists
- */
- fun set(color: Int) {
- baseColor = color
- ripples.clear()
- invalidate()
- }
-
- /**
- * Sets a color directly but with a transition
- */
- fun fade(color: Int, duration: Long = 300L) {
- ripples.clear()
- val animator = ValueAnimator.ofObject(ArgbEvaluator(), baseColor, color)
- animator.duration = duration
- animator.addUpdateListener { animation ->
- baseColor = animation.animatedValue as Int
- invalidate()
- }
- animator.start()
- }
-
- internal class Ripple(val color: Int,
- val x: Float,
- val y: Float,
- var radius: Float,
- val maxRadius: Float,
- val fade: Boolean)
-
- companion object {
- const val MIDDLE = -1.0f
- const val END = -2.0f
- const val FADE_PIVOT = 0.5f
- }
-}