aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.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/utils/Kotterknife.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/utils/Kotterknife.kt')
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt183
1 files changed, 163 insertions, 20 deletions
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt
index 3783931..f3c08bd 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt
@@ -1,3 +1,5 @@
+@file:Suppress("UNCHECKED_CAST")
+
package ca.allanwang.kau.utils
/**
@@ -13,6 +15,7 @@ import android.app.DialogFragment
import android.app.Fragment
import android.support.v7.widget.RecyclerView.ViewHolder
import android.view.View
+import java.util.*
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
import android.support.v4.app.DialogFragment as SupportDialogFragment
@@ -30,13 +33,13 @@ fun <V : View> Dialog.bindView(id: Int)
fun <V : View> DialogFragment.bindView(id: Int)
: ReadOnlyProperty<DialogFragment, V> = required(id, viewFinder)
-fun <V : View> android.support.v4.app.DialogFragment.bindView(id: Int)
+fun <V : View> SupportDialogFragment.bindView(id: Int)
: ReadOnlyProperty<android.support.v4.app.DialogFragment, V> = required(id, viewFinder)
fun <V : View> Fragment.bindView(id: Int)
: ReadOnlyProperty<Fragment, V> = required(id, viewFinder)
-fun <V : View> android.support.v4.app.Fragment.bindView(id: Int)
+fun <V : View> SupportFragment.bindView(id: Int)
: ReadOnlyProperty<android.support.v4.app.Fragment, V> = required(id, viewFinder)
fun <V : View> ViewHolder.bindView(id: Int)
@@ -54,13 +57,13 @@ fun <V : View> Dialog.bindOptionalView(id: Int)
fun <V : View> DialogFragment.bindOptionalView(id: Int)
: ReadOnlyProperty<DialogFragment, V?> = optional(id, viewFinder)
-fun <V : View> android.support.v4.app.DialogFragment.bindOptionalView(id: Int)
+fun <V : View> SupportDialogFragment.bindOptionalView(id: Int)
: ReadOnlyProperty<android.support.v4.app.DialogFragment, V?> = optional(id, viewFinder)
fun <V : View> Fragment.bindOptionalView(id: Int)
: ReadOnlyProperty<Fragment, V?> = optional(id, viewFinder)
-fun <V : View> android.support.v4.app.Fragment.bindOptionalView(id: Int)
+fun <V : View> SupportFragment.bindOptionalView(id: Int)
: ReadOnlyProperty<android.support.v4.app.Fragment, V?> = optional(id, viewFinder)
fun <V : View> ViewHolder.bindOptionalView(id: Int)
@@ -78,13 +81,13 @@ fun <V : View> Dialog.bindViews(vararg ids: Int)
fun <V : View> DialogFragment.bindViews(vararg ids: Int)
: ReadOnlyProperty<DialogFragment, List<V>> = required(ids, viewFinder)
-fun <V : View> android.support.v4.app.DialogFragment.bindViews(vararg ids: Int)
+fun <V : View> SupportDialogFragment.bindViews(vararg ids: Int)
: ReadOnlyProperty<android.support.v4.app.DialogFragment, List<V>> = required(ids, viewFinder)
fun <V : View> Fragment.bindViews(vararg ids: Int)
: ReadOnlyProperty<Fragment, List<V>> = required(ids, viewFinder)
-fun <V : View> android.support.v4.app.Fragment.bindViews(vararg ids: Int)
+fun <V : View> SupportFragment.bindViews(vararg ids: Int)
: ReadOnlyProperty<android.support.v4.app.Fragment, List<V>> = required(ids, viewFinder)
fun <V : View> ViewHolder.bindViews(vararg ids: Int)
@@ -102,13 +105,13 @@ fun <V : View> Dialog.bindOptionalViews(vararg ids: Int)
fun <V : View> DialogFragment.bindOptionalViews(vararg ids: Int)
: ReadOnlyProperty<DialogFragment, List<V>> = optional(ids, viewFinder)
-fun <V : View> android.support.v4.app.DialogFragment.bindOptionalViews(vararg ids: Int)
+fun <V : View> SupportDialogFragment.bindOptionalViews(vararg ids: Int)
: ReadOnlyProperty<android.support.v4.app.DialogFragment, List<V>> = optional(ids, viewFinder)
fun <V : View> Fragment.bindOptionalViews(vararg ids: Int)
: ReadOnlyProperty<Fragment, List<V>> = optional(ids, viewFinder)
-fun <V : View> android.support.v4.app.Fragment.bindOptionalViews(vararg ids: Int)
+fun <V : View> SupportFragment.bindOptionalViews(vararg ids: Int)
: ReadOnlyProperty<android.support.v4.app.Fragment, List<V>> = optional(ids, viewFinder)
fun <V : View> ViewHolder.bindOptionalViews(vararg ids: Int)
@@ -122,11 +125,11 @@ private inline val Dialog.viewFinder: Dialog.(Int) -> View?
get() = { findViewById(it) }
private inline val DialogFragment.viewFinder: DialogFragment.(Int) -> View?
get() = { dialog.findViewById(it) }
-private inline val android.support.v4.app.DialogFragment.viewFinder: android.support.v4.app.DialogFragment.(Int) -> View?
+private inline val SupportDialogFragment.viewFinder: SupportDialogFragment.(Int) -> View?
get() = { dialog.findViewById(it) }
private inline val Fragment.viewFinder: Fragment.(Int) -> View?
get() = { view.findViewById(it) }
-private inline val android.support.v4.app.Fragment.viewFinder: android.support.v4.app.Fragment.(Int) -> View?
+private inline val SupportFragment.viewFinder: SupportFragment.(Int) -> View?
get() = { view!!.findViewById(it) }
private inline val ViewHolder.viewFinder: ViewHolder.(Int) -> View?
get() = { itemView.findViewById(it) }
@@ -134,33 +137,173 @@ private inline val ViewHolder.viewFinder: ViewHolder.(Int) -> View?
private fun viewNotFound(id: Int, desc: KProperty<*>): Nothing =
throw IllegalStateException("View ID $id for '${desc.name}' not found.")
-@Suppress("UNCHECKED_CAST")
private fun <T, V : View> required(id: Int, finder: T.(Int) -> View?)
= Lazy { t: T, desc -> (t.finder(id) as V?)?.apply { } ?: viewNotFound(id, desc) }
-@Suppress("UNCHECKED_CAST")
private fun <T, V : View> optional(id: Int, finder: T.(Int) -> View?)
= Lazy { t: T, _ -> t.finder(id) as V? }
-@Suppress("UNCHECKED_CAST")
private fun <T, V : View> required(ids: IntArray, finder: T.(Int) -> View?)
= Lazy { t: T, desc -> ids.map { t.finder(it) as V? ?: viewNotFound(it, desc) } }
-@Suppress("UNCHECKED_CAST")
private fun <T, V : View> optional(ids: IntArray, finder: T.(Int) -> View?)
= Lazy { t: T, _ -> ids.map { t.finder(it) as V? }.filterNotNull() }
// Like Kotlin's lazy delegate but the initializer gets the target and metadata passed to it
-private class Lazy<T, V>(private val initializer: (T, KProperty<*>) -> V) : ReadOnlyProperty<T, V> {
- private object EMPTY
+private open class Lazy<in T, out V>(private val initializer: (T, KProperty<*>) -> V) : ReadOnlyProperty<T, V> {
+ protected object EMPTY
- private var value: Any? = EMPTY
+ protected var value: Any? = EMPTY
override fun getValue(thisRef: T, property: KProperty<*>): V {
- if (value == EMPTY) {
+ if (value == EMPTY)
value = initializer(thisRef, property)
- }
- @Suppress("UNCHECKED_CAST")
+
return value as V
}
+}
+
+/*
+ * The components below are a variant of the view bindings with lazy resettables
+ * All bindings are weakly held so that they may be reset through KotterknifeRegistry.reset
+ *
+ * This is typically only needed in cases such as Fragments,
+ * where their lifecycle doesn't match that of an Activity or View
+ *
+ * Credits to <a href="https://github.com/MichaelRocks">MichaelRocks</a>
+ */
+
+fun <V : View> View.bindViewResettable(id: Int)
+ : ReadOnlyProperty<View, V> = requiredResettable(id, viewFinder)
+
+fun <V : View> Activity.bindViewResettable(id: Int)
+ : ReadOnlyProperty<Activity, V> = requiredResettable(id, viewFinder)
+
+fun <V : View> Dialog.bindViewResettable(id: Int)
+ : ReadOnlyProperty<Dialog, V> = requiredResettable(id, viewFinder)
+
+fun <V : View> DialogFragment.bindViewResettable(id: Int)
+ : ReadOnlyProperty<DialogFragment, V> = requiredResettable(id, viewFinder)
+
+fun <V : View> SupportDialogFragment.bindViewResettable(id: Int)
+ : ReadOnlyProperty<android.support.v4.app.DialogFragment, V> = requiredResettable(id, viewFinder)
+
+fun <V : View> Fragment.bindViewResettable(id: Int)
+ : ReadOnlyProperty<Fragment, V> = requiredResettable(id, viewFinder)
+
+fun <V : View> SupportFragment.bindViewResettable(id: Int)
+ : ReadOnlyProperty<android.support.v4.app.Fragment, V> = requiredResettable(id, viewFinder)
+
+fun <V : View> ViewHolder.bindViewResettable(id: Int)
+ : ReadOnlyProperty<ViewHolder, V> = requiredResettable(id, viewFinder)
+
+fun <V : View> View.bindOptionalViewResettable(id: Int)
+ : ReadOnlyProperty<View, V?> = optionalResettable(id, viewFinder)
+
+fun <V : View> Activity.bindOptionalViewResettable(id: Int)
+ : ReadOnlyProperty<Activity, V?> = optionalResettable(id, viewFinder)
+
+fun <V : View> Dialog.bindOptionalViewResettable(id: Int)
+ : ReadOnlyProperty<Dialog, V?> = optionalResettable(id, viewFinder)
+
+fun <V : View> DialogFragment.bindOptionalViewResettable(id: Int)
+ : ReadOnlyProperty<DialogFragment, V?> = optionalResettable(id, viewFinder)
+
+fun <V : View> SupportDialogFragment.bindOptionalViewResettable(id: Int)
+ : ReadOnlyProperty<android.support.v4.app.DialogFragment, V?> = optionalResettable(id, viewFinder)
+
+fun <V : View> Fragment.bindOptionalViewResettable(id: Int)
+ : ReadOnlyProperty<Fragment, V?> = optionalResettable(id, viewFinder)
+
+fun <V : View> SupportFragment.bindOptionalViewResettable(id: Int)
+ : ReadOnlyProperty<android.support.v4.app.Fragment, V?> = optionalResettable(id, viewFinder)
+
+fun <V : View> ViewHolder.bindOptionalViewResettable(id: Int)
+ : ReadOnlyProperty<ViewHolder, V?> = optionalResettable(id, viewFinder)
+
+fun <V : View> View.bindViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<View, List<V>> = requiredResettable(ids, viewFinder)
+
+fun <V : View> Activity.bindViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<Activity, List<V>> = requiredResettable(ids, viewFinder)
+
+fun <V : View> Dialog.bindViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<Dialog, List<V>> = requiredResettable(ids, viewFinder)
+
+fun <V : View> DialogFragment.bindViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<DialogFragment, List<V>> = requiredResettable(ids, viewFinder)
+
+fun <V : View> SupportDialogFragment.bindViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<android.support.v4.app.DialogFragment, List<V>> = requiredResettable(ids, viewFinder)
+
+fun <V : View> Fragment.bindViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<Fragment, List<V>> = requiredResettable(ids, viewFinder)
+
+fun <V : View> SupportFragment.bindViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<android.support.v4.app.Fragment, List<V>> = requiredResettable(ids, viewFinder)
+
+fun <V : View> ViewHolder.bindViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<ViewHolder, List<V>> = requiredResettable(ids, viewFinder)
+
+fun <V : View> View.bindOptionalViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<View, List<V>> = optionalResettable(ids, viewFinder)
+
+fun <V : View> Activity.bindOptionalViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<Activity, List<V>> = optionalResettable(ids, viewFinder)
+
+fun <V : View> Dialog.bindOptionalViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<Dialog, List<V>> = optionalResettable(ids, viewFinder)
+
+fun <V : View> DialogFragment.bindOptionalViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<DialogFragment, List<V>> = optionalResettable(ids, viewFinder)
+
+fun <V : View> SupportDialogFragment.bindOptionalViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<android.support.v4.app.DialogFragment, List<V>> = optionalResettable(ids, viewFinder)
+
+fun <V : View> Fragment.bindOptionalViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<Fragment, List<V>> = optionalResettable(ids, viewFinder)
+
+fun <V : View> SupportFragment.bindOptionalViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<android.support.v4.app.Fragment, List<V>> = optionalResettable(ids, viewFinder)
+
+fun <V : View> ViewHolder.bindOptionalViewsResettable(vararg ids: Int)
+ : ReadOnlyProperty<ViewHolder, List<V>> = optionalResettable(ids, viewFinder)
+
+private fun <T, V : View> requiredResettable(id: Int, finder: T.(Int) -> View?)
+ = LazyResettable { t: T, desc -> (t.finder(id) as V?)?.apply { } ?: viewNotFound(id, desc) }
+
+private fun <T, V : View> optionalResettable(id: Int, finder: T.(Int) -> View?)
+ = LazyResettable { t: T, _ -> t.finder(id) as V? }
+
+private fun <T, V : View> requiredResettable(ids: IntArray, finder: T.(Int) -> View?)
+ = LazyResettable { t: T, desc -> ids.map { t.finder(it) as V? ?: viewNotFound(it, desc) } }
+
+private fun <T, V : View> optionalResettable(ids: IntArray, finder: T.(Int) -> View?)
+ = LazyResettable { t: T, _ -> ids.map { t.finder(it) as V? }.filterNotNull() }
+
+//Like Kotterknife's lazy delegate but is resettable
+private class LazyResettable<in T, out V>(initializer: (T, KProperty<*>) -> V) : Lazy<T, V>(initializer) {
+ override fun getValue(thisRef: T, property: KProperty<*>): V {
+ KotterknifeRegistry.register(thisRef!!, this)
+ return super.getValue(thisRef, property)
+ }
+
+ fun reset() {
+ value = EMPTY
+ }
+}
+
+object Kotterknife {
+ fun reset(target: Any) {
+ KotterknifeRegistry.reset(target)
+ }
+}
+
+private object KotterknifeRegistry {
+ private val lazyMap = WeakHashMap<Any, MutableCollection<LazyResettable<*, *>>>()
+
+ fun register(target: Any, lazy: LazyResettable<*, *>)
+ = lazyMap.getOrPut(target, { Collections.newSetFromMap(WeakHashMap()) }).add(lazy)
+
+ fun reset(target: Any) = lazyMap[target]?.forEach { it.reset() }
} \ No newline at end of file