aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/ca/allanwang/kau/utils
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
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')
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt5
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt15
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/Const.kt6
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt183
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt3
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt54
6 files changed, 223 insertions, 43 deletions
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt
index 112c8ec..5da21bb 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt
@@ -6,6 +6,7 @@ import android.annotation.SuppressLint
import android.support.annotation.StringRes
import android.view.View
import android.view.ViewAnimationUtils
+import android.view.ViewPropertyAnimator
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.TextView
@@ -123,4 +124,6 @@ import android.widget.TextView
})
}
-@KauUtils fun TextView.setTextWithFade(@StringRes textId: Int, duration: Long = 200, onFinish: (() -> Unit)? = null) = setTextWithFade(context.getString(textId), duration, onFinish) \ No newline at end of file
+@KauUtils fun TextView.setTextWithFade(@StringRes textId: Int, duration: Long = 200, onFinish: (() -> Unit)? = null) = setTextWithFade(context.getString(textId), duration, onFinish)
+
+@KauUtils inline fun ViewPropertyAnimator.scaleXY(value: Float) = scaleX(value).scaleY(value) \ No newline at end of file
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt
index 50d117c..8537185 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt
@@ -15,10 +15,25 @@ import android.support.v7.widget.AppCompatEditText
import android.support.v7.widget.Toolbar
import android.widget.*
import com.afollestad.materialdialogs.R
+import java.util.*
/**
* Created by Allan Wang on 2017-06-08.
*/
+
+/**
+ * Generates a random opaque color
+ * Note that this is mainly for testing
+ * Should you require this method often, consider
+ * rewriting the method and storing the [Random] instance
+ * rather than generating one each time
+ */
+inline val rndColor: Int
+ get() {
+ val rnd = Random()
+ return Color.rgb(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256))
+ }
+
inline val Int.isColorDark: Boolean
get() = isColorDark(0.5f)
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/Const.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/Const.kt
index f267a60..3e90926 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/Const.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/Const.kt
@@ -9,6 +9,6 @@ const val KAU_LEFT = 1
const val KAU_TOP = 2
const val KAU_RIGHT = 4
const val KAU_BOTTOM = 8
-const val KAU_HORIZONTAL = KAU_LEFT and KAU_RIGHT
-const val KAU_VERTICAL = KAU_TOP and KAU_BOTTOM
-const val KAU_ALL = KAU_HORIZONTAL and KAU_VERTICAL \ No newline at end of file
+const val KAU_HORIZONTAL = KAU_LEFT or KAU_RIGHT
+const val KAU_VERTICAL = KAU_TOP or KAU_BOTTOM
+const val KAU_ALL = KAU_HORIZONTAL or KAU_VERTICAL \ No newline at end of file
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
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt
index 36bcc93..42d150e 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt
@@ -1,5 +1,6 @@
package ca.allanwang.kau.utils
+import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
@@ -31,11 +32,9 @@ import android.os.Build
}
inline val buildIsMarshmallowAndUp: Boolean
-
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
inline val buildIsLollipopAndUp: Boolean
- @SuppressWarnings("NewApi")
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
inline val buildIsNougatAndUp: Boolean
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
index ead2cb7..53d711d 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
@@ -3,20 +3,21 @@
package ca.allanwang.kau.utils
import android.animation.ValueAnimator
+import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.os.Build
-import android.support.annotation.*
+import android.support.annotation.ColorInt
+import android.support.annotation.ColorRes
+import android.support.annotation.RequiresApi
+import android.support.annotation.StringRes
import android.support.design.widget.FloatingActionButton
import android.support.design.widget.Snackbar
import android.support.design.widget.TextInputEditText
-import android.support.transition.AutoTransition
-import android.support.transition.Transition
-import android.support.transition.TransitionInflater
-import android.support.transition.TransitionManager
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
+import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
@@ -135,7 +136,6 @@ fun FloatingActionButton.hideIf(hide: Boolean) = if (hide) hide() else show()
if (flag and KAU_RIGHT > 0) margin else p.rightMargin,
if (flag and KAU_BOTTOM > 0) margin else p.bottomMargin
)
- requestLayout()
return true
}
@@ -184,7 +184,6 @@ fun FloatingActionButton.hideIf(hide: Boolean) = if (hide) hide() else show()
if (flag and KAU_RIGHT > 0) padding else paddingRight,
if (flag and KAU_BOTTOM > 0) padding else paddingBottom
)
- requestLayout()
}
@KauUtils fun View.hideKeyboard() {
@@ -222,23 +221,19 @@ fun Context.fullLinearRecycler(rvAdapter: RecyclerView.Adapter<*>? = null, confi
}
/**
- * Animate a transition for a FloatinActionButton
+ * Animate a transition a given imageview
* If it is not shown, the action will be invoked directly and the fab will be shown
* If it is already shown, scaling and alpha animations will be added to the action
*/
-inline fun FloatingActionButton.transition(crossinline action: FloatingActionButton.() -> Unit) {
- if (isHidden) {
- action()
- show()
- } else {
+inline fun <T : ImageView> T.fadeScaleTransition(duration: Long = 500L, minScale: Float = 0.7f, crossinline action: T.() -> Unit) {
+ if (!isVisible) action()
+ else {
var transitioned = false
ValueAnimator.ofFloat(1.0f, 0.0f, 1.0f).apply {
- duration = 500L
+ this.duration = duration
addUpdateListener {
val x = it.animatedValue as Float
- val scale = x * 0.3f + 0.7f
- scaleX = scale
- scaleY = scale
+ scaleXY = x * (1 - minScale) + minScale
imageAlpha = (x * 255).toInt()
if (it.animatedFraction > 0.5f && !transitioned) {
transitioned = true
@@ -266,4 +261,29 @@ fun FloatingActionButton.hideOnDownwardsScroll(recycler: RecyclerView) {
else if (dy < 0 && isHidden) show()
}
})
+}
+
+inline var View.scaleXY
+ get() = Math.max(scaleX, scaleY)
+ set(value) {
+ scaleX = value
+ scaleY = value
+ }
+
+/**
+ * Creates an on touch listener that only emits on a short single tap
+ */
+@SuppressLint("ClickableViewAccessibility")
+inline fun View.setOnSingleTapListener(crossinline onSingleTap: (v: View, event: MotionEvent) -> Unit) {
+ setOnTouchListener { v, event ->
+ when (event.actionMasked) {
+ MotionEvent.ACTION_DOWN -> true
+ MotionEvent.ACTION_UP -> {
+ if (event.eventTime - event.downTime < 100)
+ onSingleTap(v, event)
+ true
+ }
+ else -> false
+ }
+ }
} \ No newline at end of file