aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2017-07-31 23:02:01 -0700
committerGitHub <noreply@github.com>2017-07-31 23:02:01 -0700
commit48213d0b427c478865c75fee912ff1ae8bbaffb5 (patch)
tree7aef1d8400fc3403ee5a40aba945f33a95319359 /core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt
parent8a4e9fd44dfbcf58aa7ab63167dcbdf8752db7d0 (diff)
downloadkau-48213d0b427c478865c75fee912ff1ae8bbaffb5.tar.gz
kau-48213d0b427c478865c75fee912ff1ae8bbaffb5.tar.bz2
kau-48213d0b427c478865c75fee912ff1ae8bbaffb5.zip
Major update to core and kotterknife; create mediapicker (#15)
* Readme * Fix kau direction bits * Truly support transparent ripples * Update changelog * Test rect as base * Replace fab transition with generic fade scale transition * Add scalexy func * Add scaleXY * Add arguments to fadeScaleTransition * Clean up ink indicator * Create setOnSingleTapListener * Fix lint and add rndColor * Create kotterknife resettables * Add readme and missing object * Create lazy resettable registered * Update core docs * Opt for separate class for resettable registry * Clean up resettable registry * Rename functions * Add ripple callback listener * Adjust kprefactivity desc color * Add more transitions * Add delete keys option * Add instrumentation tests * switch id * Revert automatic instrumental tests * Generify imagepickercore and prepare video alternative * Create working video picker * Address possible null issue * Update searchview * Make layouts public * Add changelog test * Update logo link * Add custom color gif
Diffstat (limited to 'core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt')
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt90
1 files changed, 38 insertions, 52 deletions
diff --git a/core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt b/core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt
index 773490c..f587e60 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt
@@ -1,14 +1,13 @@
package ca.allanwang.kau.ui.views
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
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.graphics.*
import android.util.AttributeSet
import android.view.View
-import ca.allanwang.kau.utils.adjustAlpha
/**
* Created by Allan Wang on 2016-11-17.
@@ -21,63 +20,45 @@ import ca.allanwang.kau.utils.adjustAlpha
class RippleCanvas @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
- private val paint: Paint = Paint()
+ private val paint: Paint = Paint().apply {
+ isAntiAlias = true
+ style = Paint.Style.FILL
+ }
+ private val eraser: Paint = Paint().apply {
+ style = Paint.Style.FILL
+ xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
+ }
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
+ * Draw ripples one at a time in the order given
+ * To support transparent ripples, we simply erase the overlapping base before adding a new circle
*/
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
+ paint.color = baseColor
+ canvas.drawRect(0f, 0f, canvas.width.toFloat(), canvas.height.toFloat(), paint)
+ val itr = ripples.iterator()
+ while (itr.hasNext()) {
+ val r = itr.next()
+ paint.color = r.color
+ canvas.drawCircle(r.x, r.y, r.radius, eraser)
+ canvas.drawCircle(r.x, r.y, r.radius, paint)
+ if (r.radius == r.maxRadius) {
+ itr.remove()
+ baseColor = r.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) {
+ fun ripple(color: Int,
+ startX: Float = 0f,
+ startY: Float = 0f,
+ duration: Long = 600L,
+ callback: (() -> Unit)? = null) {
val w = width.toFloat()
val h = height.toFloat()
val x = when (startX) {
@@ -91,7 +72,7 @@ class RippleCanvas @JvmOverloads constructor(
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)
+ val ripple = Ripple(color, x, y, 0f, maxRadius)
ripples.add(ripple)
val animator = ValueAnimator.ofFloat(0f, maxRadius)
animator.duration = duration
@@ -99,6 +80,11 @@ class RippleCanvas @JvmOverloads constructor(
ripple.radius = animation.animatedValue as Float
invalidate()
}
+ if (callback != null)
+ animator.addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationCancel(animation: Animator?) = callback()
+ override fun onAnimationEnd(animation: Animator?) = callback()
+ })
animator.start()
}
@@ -111,6 +97,8 @@ class RippleCanvas @JvmOverloads constructor(
invalidate()
}
+ override fun setBackgroundColor(color: Int) = set(color)
+
/**
* Sets a color directly but with a transition
*/
@@ -129,12 +117,10 @@ class RippleCanvas @JvmOverloads constructor(
val x: Float,
val y: Float,
var radius: Float,
- val maxRadius: Float,
- val fade: Boolean)
+ val maxRadius: Float)
companion object {
const val MIDDLE = -1.0f
const val END = -2.0f
- const val FADE_PIVOT = 0.5f
}
}