aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/utils/AnimatedVectorDelegate.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/utils/AnimatedVectorDelegate.kt')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/AnimatedVectorDelegate.kt82
1 files changed, 82 insertions, 0 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/AnimatedVectorDelegate.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/AnimatedVectorDelegate.kt
new file mode 100644
index 00000000..a530df32
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/AnimatedVectorDelegate.kt
@@ -0,0 +1,82 @@
+package com.pitchedapps.frost.utils
+
+import android.graphics.drawable.AnimatedVectorDrawable
+import android.support.annotation.DrawableRes
+import android.widget.ImageView
+import ca.allanwang.kau.utils.drawable
+
+/**
+ * Created by Allan Wang on 2017-07-29.
+ *
+ * Delegate for animated vector drawables with two states (start and end)
+ * Drawables are added lazily depending on the animation direction, and are verified upon load
+ * Should the bounded view not have an animated drawable upon animating, it is assumed
+ * that the user has switched the resource themselves and the delegate will not switch the resource
+ */
+interface AnimatedVectorContract {
+ fun animate()
+ fun animateReverse()
+ fun animateToggle()
+ val isAtStart: Boolean
+ fun bind(view: ImageView)
+ var animatedVectorListener: ((avd: AnimatedVectorDrawable, forwards: Boolean) -> Unit)?
+}
+
+class AnimatedVectorDelegate(
+ /**
+ * The res for the starting resource; must have parent tag animated-vector
+ */
+ @param:DrawableRes val avdStart: Int,
+ /**
+ * The res for the ending resource; must have parent tag animated-vector
+ */
+ @param:DrawableRes val avdEnd: Int,
+ /**
+ * The delegate will automatically set the start resource when bound
+ * If [emitOnBind] is true, it will also trigger the listener
+ */
+ val emitOnBind: Boolean = true,
+ /**
+ * The optional listener that will be triggered every time the avd is switched by the delegate
+ */
+ override var animatedVectorListener: ((avd: AnimatedVectorDrawable, forwards: Boolean) -> Unit)? = null
+) : AnimatedVectorContract {
+
+ lateinit var view: ImageView
+
+ private var atStart = true
+
+ override val isAtStart: Boolean
+ get() = atStart
+
+ private val avd: AnimatedVectorDrawable?
+ get() = view.drawable as? AnimatedVectorDrawable
+
+ override fun bind(view: ImageView) {
+ this.view = view
+ view.context.drawable(avdStart) as? AnimatedVectorDrawable ?: throw IllegalArgumentException("AnimatedVectorDelegate has a starting drawable that isn't an avd")
+ view.context.drawable(avdEnd) as? AnimatedVectorDrawable ?: throw IllegalArgumentException("AnimatedVectorDelegate has an ending drawable that isn't an avd")
+ view.setImageResource(avdStart)
+ if (emitOnBind) animatedVectorListener?.invoke(avd!!, false)
+ }
+
+ override fun animate() = animateImpl(false)
+
+ override fun animateReverse() = animateImpl(true)
+
+ override fun animateToggle() = animateImpl(!atStart)
+
+ private fun animateImpl(toStart: Boolean) {
+ if ((atStart == toStart)) return L.d("AVD already at ${if (toStart) "start" else "end"}")
+ if (avd == null) return L.d("AVD null resource")//no longer using animated vector; do not modify
+ avd?.stop()
+ view.setImageResource(if (toStart) avdEnd else avdStart)
+ animatedVectorListener?.invoke(avd!!, !toStart)
+ atStart = toStart
+ avd?.start()
+ }
+
+}
+
+
+