From 2588d7bd473203dbd0a09f6a6cbb0a3f0b5c0c19 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sun, 25 Jun 2017 11:31:31 -0700 Subject: More annotations --- .../ca/allanwang/kau/searchview/SearchItem.kt | 30 +++++++++----- .../kotlin/ca/allanwang/kau/utils/AnimUtils.kt | 48 +++++++++++----------- .../kotlin/ca/allanwang/kau/utils/FragmentUtils.kt | 2 +- .../kotlin/ca/allanwang/kau/utils/IIconUtils.kt | 2 +- .../kotlin/ca/allanwang/kau/utils/PackageUtils.kt | 2 +- .../ca/allanwang/kau/utils/TransitionUtils.kt | 2 +- .../main/kotlin/ca/allanwang/kau/utils/Utils.kt | 17 +++++--- .../kotlin/ca/allanwang/kau/utils/ViewUtils.kt | 27 +++++++----- .../ca/allanwang/kau/views/SimpleRippleDrawable.kt | 10 +++-- library/src/main/res/layout/kau_search_item.xml | 38 +++++++++++++---- library/src/main/res/values/dimens_search.xml | 1 + 11 files changed, 114 insertions(+), 65 deletions(-) diff --git a/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt b/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt index f8b6ab6..6fea9b0 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt @@ -1,14 +1,13 @@ package ca.allanwang.kau.searchview +import android.graphics.drawable.Drawable import android.support.v7.widget.RecyclerView import android.view.View import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import ca.allanwang.kau.R -import ca.allanwang.kau.utils.bindView -import ca.allanwang.kau.utils.setIcon -import ca.allanwang.kau.views.SimpleRippleDrawable +import ca.allanwang.kau.utils.* import com.mikepenz.fastadapter.items.AbstractItem import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.typeface.IIcon @@ -20,7 +19,11 @@ import com.mikepenz.iconics.typeface.IIcon * Contains a [key] which acts as a unique identifier (eg url) * and a [content] which is displayed in the item */ -class SearchItem(val key: String, val content: String = key, val iicon: IIcon? = GoogleMaterial.Icon.gmd_search +class SearchItem(val key: String, + val content: String = key, + val description: String? = null, + val iicon: IIcon? = GoogleMaterial.Icon.gmd_search, + val image: Drawable? = null ) : AbstractItem() { companion object { @@ -36,21 +39,28 @@ class SearchItem(val key: String, val content: String = key, val iicon: IIcon? = override fun bindView(holder: ViewHolder, payloads: MutableList?) { super.bindView(holder, payloads) - holder.text.setTextColor(foregroundColor) - holder.icon.setIcon(iicon, sizeDp = 18, color = foregroundColor) - holder.container.background = SimpleRippleDrawable(foregroundColor, backgroundColor) - holder.text.text = content + holder.title.setTextColor(foregroundColor) + holder.desc.setTextColor(foregroundColor.adjustAlpha(0.6f)) + + if (image != null) holder.icon.setImageDrawable(image) + else holder.icon.setIcon(iicon, sizeDp = 18, color = foregroundColor) + + holder.container.setRippleBackground(foregroundColor, backgroundColor) + holder.title.text = content + if (description?.isNotBlank() ?: false) holder.desc.visible().text = description } override fun unbindView(holder: ViewHolder) { super.unbindView(holder) - holder.text.text = null + holder.title.text = null + holder.desc.gone().text = null holder.icon.setImageDrawable(null) } class ViewHolder(v: View) : RecyclerView.ViewHolder(v) { val icon: ImageView by bindView(R.id.search_icon) - val text: TextView by bindView(R.id.search_text) + val title: TextView by bindView(R.id.search_title) + val desc: TextView by bindView(R.id.search_desc) val container: LinearLayout by bindView(R.id.search_item_frame) } } \ No newline at end of file diff --git a/library/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt b/library/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt index 3cf3309..cde332a 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt @@ -13,11 +13,11 @@ import android.widget.TextView /** * Created by Allan Wang on 2017-06-01. * - * Animation extension functions for Views + * Animation extension @KauUtils functions for Views */ -fun View.rootCircularReveal(x: Int = 0, y: Int = 0, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { +@KauUtils fun View.rootCircularReveal(x: Int = 0, y: Int = 0, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { this.addOnLayoutChangeListener(object : View.OnLayoutChangeListener { - override fun onLayoutChange(v: View, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, + override @KauUtils fun onLayoutChange(v: View, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) { v.removeOnLayoutChangeListener(this) var x2 = x @@ -29,20 +29,20 @@ fun View.rootCircularReveal(x: Int = 0, y: Int = 0, duration: Long = 500L, onSta reveal.interpolator = DecelerateInterpolator(1f) reveal.duration = duration reveal.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationStart(animation: Animator?) { + override @KauUtils fun onAnimationStart(animation: Animator?) { visible() onStart?.invoke() } - override fun onAnimationEnd(animation: Animator?) = onFinish?.invoke() ?: Unit - override fun onAnimationCancel(animation: Animator?) = onFinish?.invoke() ?: Unit + override @KauUtils fun onAnimationEnd(animation: Animator?) = onFinish?.invoke() ?: Unit + override @KauUtils fun onAnimationCancel(animation: Animator?) = onFinish?.invoke() ?: Unit }) reveal.start() } }) } -fun View.circularReveal(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float = -1.0f, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { +@KauUtils fun View.circularReveal(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float = -1.0f, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { if (!isAttachedToWindow) { onStart?.invoke() visible() @@ -56,18 +56,18 @@ fun View.circularReveal(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float val anim = ViewAnimationUtils.createCircularReveal(this, x, y, 0f, r).setDuration(duration) anim.startDelay = offset anim.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationStart(animation: Animator?) { + override @KauUtils fun onAnimationStart(animation: Animator?) { visible() onStart?.invoke() } - override fun onAnimationEnd(animation: Animator?) = onFinish?.invoke() ?: Unit - override fun onAnimationCancel(animation: Animator?) = onFinish?.invoke() ?: Unit + override @KauUtils fun onAnimationEnd(animation: Animator?) = onFinish?.invoke() ?: Unit + override @KauUtils fun onAnimationCancel(animation: Animator?) = onFinish?.invoke() ?: Unit }) anim.start() } -fun View.circularHide(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float = -1.0f, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { +@KauUtils fun View.circularHide(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float = -1.0f, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { if (!isAttachedToWindow) { onStart?.invoke() invisible() @@ -81,19 +81,19 @@ fun View.circularHide(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float = val anim = ViewAnimationUtils.createCircularReveal(this, x, y, r, 0f).setDuration(duration) anim.startDelay = offset anim.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationStart(animation: Animator?) = onStart?.invoke() ?: Unit + override @KauUtils fun onAnimationStart(animation: Animator?) = onStart?.invoke() ?: Unit - override fun onAnimationEnd(animation: Animator?) { + override @KauUtils fun onAnimationEnd(animation: Animator?) { invisible() onFinish?.invoke() ?: Unit } - override fun onAnimationCancel(animation: Animator?) = onFinish?.invoke() ?: Unit + override @KauUtils fun onAnimationCancel(animation: Animator?) = onFinish?.invoke() ?: Unit }) anim.start() } -fun View.fadeIn(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { +@KauUtils fun View.fadeIn(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { if (!isAttachedToWindow) { onStart?.invoke() visible() @@ -105,9 +105,9 @@ fun View.fadeIn(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? anim.startOffset = offset anim.duration = duration anim.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) {} - override fun onAnimationEnd(animation: Animation?) = onFinish?.invoke() ?: Unit - override fun onAnimationStart(animation: Animation?) { + override @KauUtils fun onAnimationRepeat(animation: Animation?) {} + override @KauUtils fun onAnimationEnd(animation: Animation?) = onFinish?.invoke() ?: Unit + override @KauUtils fun onAnimationStart(animation: Animation?) { visible() onStart?.invoke() } @@ -116,7 +116,7 @@ fun View.fadeIn(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? } } -fun View.fadeOut(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { +@KauUtils fun View.fadeOut(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { if (!isAttachedToWindow) { onStart?.invoke() invisible() @@ -127,25 +127,25 @@ fun View.fadeOut(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit) anim.startOffset = offset anim.duration = duration anim.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) {} - override fun onAnimationEnd(animation: Animation?) { + override @KauUtils fun onAnimationRepeat(animation: Animation?) {} + override @KauUtils fun onAnimationEnd(animation: Animation?) { invisible() onFinish?.invoke() } - override fun onAnimationStart(animation: Animation?) { + override @KauUtils fun onAnimationStart(animation: Animation?) { onStart?.invoke() } }) startAnimation(anim) } -fun TextView.setTextWithFade(text: String, duration: Long = 200, onFinish: (() -> Unit)? = null) { +@KauUtils fun TextView.setTextWithFade(text: String, duration: Long = 200, onFinish: (() -> Unit)? = null) { fadeOut(duration = duration, onFinish = { setText(text) fadeIn(duration = duration, onFinish = onFinish) }) } -fun TextView.setTextWithFade(@StringRes textId: Int, duration: Long = 200, onFinish: (() -> Unit)? = null) = setTextWithFade(context.getString(textId), duration, onFinish) +@KauUtils fun TextView.setTextWithFade(@StringRes textId: Int, duration: Long = 200, onFinish: (() -> Unit)? = null) = setTextWithFade(context.getString(textId), duration, onFinish) diff --git a/library/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt b/library/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt index f97b4d3..cf0be7d 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt @@ -6,7 +6,7 @@ import android.support.v4.app.Fragment /** * Created by Allan Wang on 2017-05-29. */ -fun T.withBundle(builder: Bundle.() -> Unit = {}): T { +@KauUtils fun T.withBundle(builder: Bundle.() -> Unit = {}): T { if (this.arguments == null) this.arguments = Bundle() this.arguments.builder() return this diff --git a/library/src/main/kotlin/ca/allanwang/kau/utils/IIconUtils.kt b/library/src/main/kotlin/ca/allanwang/kau/utils/IIconUtils.kt index 4bb72a8..03a1605 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/utils/IIconUtils.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/utils/IIconUtils.kt @@ -11,7 +11,7 @@ import com.mikepenz.iconics.typeface.IIcon /** * Created by Allan Wang on 2017-05-29. */ -fun IIcon.toDrawable(c: Context, sizeDp: Int = 24, @ColorInt color: Int = Color.WHITE, builder: IconicsDrawable.() -> Unit = {}): Drawable { +@KauUtils fun IIcon.toDrawable(c: Context, sizeDp: Int = 24, @ColorInt color: Int = Color.WHITE, builder: IconicsDrawable.() -> Unit = {}): Drawable { val state = ColorStateList.valueOf(color) val icon = IconicsDrawable(c).icon(this).sizeDp(sizeDp) icon.setTintList(state) diff --git a/library/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt b/library/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt index 646c0dd..f2703dc 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt @@ -13,7 +13,7 @@ import android.os.Build * @param packageName packageId * @return true if installed with activity, false otherwise */ -fun Context.isAppInstalled(packageName: String): Boolean { +@KauUtils fun Context.isAppInstalled(packageName: String): Boolean { val pm = packageManager var installed: Boolean try { diff --git a/library/src/main/kotlin/ca/allanwang/kau/utils/TransitionUtils.kt b/library/src/main/kotlin/ca/allanwang/kau/utils/TransitionUtils.kt index 9f74c86..9e668d0 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/utils/TransitionUtils.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/utils/TransitionUtils.kt @@ -14,6 +14,6 @@ class TransitionEndListener(val onEnd: (transition: Transition) -> Unit) : Trans override fun onTransitionStart(transition: Transition) {} } -fun TransitionSet.addEndListener(onEnd: (transition: Transition) -> Unit) { +@KauUtils fun TransitionSet.addEndListener(onEnd: (transition: Transition) -> Unit) { addListener(TransitionEndListener(onEnd)) } \ No newline at end of file diff --git a/library/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt b/library/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt index 629dfb2..c44fc9a 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt @@ -16,16 +16,23 @@ import java.text.DecimalFormat * Created by Allan Wang on 2017-05-28. */ -val Int.dpToPx: Int +/** + * Markers to isolate respective extension @KauUtils functions to their extended class + * Avoids having a whole bunch of methods for nested calls + */ +@DslMarker +annotation class KauUtils + +@KauUtils val Int.dpToPx: Int get() = (this * Resources.getSystem().displayMetrics.density).toInt() -val Int.pxToDp: Int +@KauUtils val Int.pxToDp: Int get() = (this / Resources.getSystem().displayMetrics.density).toInt() /** * Log whether current state is in the main thread */ -fun checkThread(id: Int) { +@KauUtils fun checkThread(id: Int) { val status = if (Looper.myLooper() == Looper.getMainLooper()) "is" else "is not" KL.d("$id $status in the main thread") } @@ -34,7 +41,7 @@ fun checkThread(id: Int) { * Converts minute value to string * Whole hours and days will be converted as such, otherwise it will default to x minutes */ -fun Context.minuteToText(minutes: Long): String = with(minutes) { +@KauUtils fun Context.minuteToText(minutes: Long): String = with(minutes) { if (this < 0L) string(R.string.kau_none) else if (this == 60L) string(R.string.kau_one_hour) else if (this == 1440L) string(R.string.kau_one_day) @@ -43,7 +50,7 @@ fun Context.minuteToText(minutes: Long): String = with(minutes) { else String.format(string(R.string.kau_x_minutes), this) } -fun Number.round(@IntRange(from = 1L) decimalCount: Int): String { +@KauUtils fun Number.round(@IntRange(from = 1L) decimalCount: Int): String { val expression = StringBuilder().append("#.") (1..decimalCount).forEach { expression.append("#") } val formatter = DecimalFormat(expression.toString()) diff --git a/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt b/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt index 20ffb4b..2b7d888 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt @@ -12,6 +12,7 @@ import android.view.ViewGroup import android.view.inputmethod.InputMethodManager import android.widget.ImageView import android.widget.TextView +import ca.allanwang.kau.views.createSimpleRippleDrawable import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.IIcon @@ -19,24 +20,24 @@ import com.mikepenz.iconics.typeface.IIcon /** * Created by Allan Wang on 2017-05-31. */ -fun T.visible(): T { +@KauUtils fun T.visible(): T { visibility = View.VISIBLE return this } -fun T.invisible(): T { +@KauUtils fun T.invisible(): T { visibility = View.INVISIBLE return this } -fun T.gone(): T { +@KauUtils fun T.gone(): T { visibility = View.GONE return this } -fun View.isVisible(): Boolean = visibility == View.VISIBLE -fun View.isInvisible(): Boolean = visibility == View.INVISIBLE -fun View.isGone(): Boolean = visibility == View.GONE +@KauUtils fun View.isVisible(): Boolean = visibility == View.VISIBLE +@KauUtils fun View.isInvisible(): Boolean = visibility == View.INVISIBLE +@KauUtils fun View.isGone(): Boolean = visibility == View.GONE fun View.snackbar(text: String, duration: Int = Snackbar.LENGTH_LONG, builder: (Snackbar) -> Unit = {}) { val snackbar = Snackbar.make(this, text, duration) @@ -47,27 +48,31 @@ fun View.snackbar(text: String, duration: Int = Snackbar.LENGTH_LONG, builder: ( fun View.snackbar(@StringRes textId: Int, duration: Int = Snackbar.LENGTH_LONG, builder: (Snackbar) -> Unit = {}) = snackbar(context.string(textId), duration, builder) -fun TextView.setTextIfValid(@StringRes id: Int) { +@KauUtils fun TextView.setTextIfValid(@StringRes id: Int) { if (id > 0) text = context.string(id) } -fun ImageView.setIcon(icon: IIcon?, sizeDp: Int = 24, @ColorInt color: Int = Color.WHITE, builder: IconicsDrawable.() -> Unit = {}) { +@KauUtils fun ImageView.setIcon(icon: IIcon?, sizeDp: Int = 24, @ColorInt color: Int = Color.WHITE, builder: IconicsDrawable.() -> Unit = {}) { if (icon == null) return setImageDrawable(icon.toDrawable(context, sizeDp = sizeDp, color = color, builder = builder)) } -fun View.hideKeyboard() { +@KauUtils fun View.hideKeyboard() { clearFocus() (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(windowToken, 0) } -fun View.showKeyboard() { +@KauUtils fun View.showKeyboard() { requestFocus() (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).showSoftInput(this, InputMethodManager.SHOW_IMPLICIT) } -fun ViewGroup.transitionAuto(builder: AutoTransition.() -> Unit = {}) { +@KauUtils fun ViewGroup.transitionAuto(builder: AutoTransition.() -> Unit = {}) { val transition = AutoTransition() transition.builder() TransitionManager.beginDelayedTransition(this, transition) } + +@KauUtils fun View.setRippleBackground(@ColorInt foregroundColor: Int, @ColorInt backgroundColor: Int) { + background = createSimpleRippleDrawable(foregroundColor, backgroundColor) +} \ No newline at end of file diff --git a/library/src/main/kotlin/ca/allanwang/kau/views/SimpleRippleDrawable.kt b/library/src/main/kotlin/ca/allanwang/kau/views/SimpleRippleDrawable.kt index fbaad1a..df842f6 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/views/SimpleRippleDrawable.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/views/SimpleRippleDrawable.kt @@ -4,7 +4,6 @@ import android.content.res.ColorStateList import android.graphics.drawable.ColorDrawable import android.graphics.drawable.RippleDrawable import android.support.annotation.ColorInt -import ca.allanwang.kau.searchview.SearchItem import ca.allanwang.kau.utils.adjustAlpha /** @@ -12,6 +11,9 @@ import ca.allanwang.kau.utils.adjustAlpha * * Tries to mimic a standard ripple, given the foreground and background colors */ -class SimpleRippleDrawable(@ColorInt foregroundColor: Int, @ColorInt backgroundColor: Int -) : RippleDrawable(ColorStateList(arrayOf(intArrayOf()), intArrayOf(foregroundColor)), - ColorDrawable(backgroundColor), ColorDrawable(foregroundColor.adjustAlpha(0.16f))) \ No newline at end of file +fun createSimpleRippleDrawable(@ColorInt foregroundColor: Int, @ColorInt backgroundColor: Int): RippleDrawable { + val states = ColorStateList(arrayOf(intArrayOf()), intArrayOf(foregroundColor)) + val content = ColorDrawable(backgroundColor) + val mask = ColorDrawable(foregroundColor.adjustAlpha(0.16f)) + return RippleDrawable(states, content, mask) +} \ No newline at end of file diff --git a/library/src/main/res/layout/kau_search_item.xml b/library/src/main/res/layout/kau_search_item.xml index 20f3ef2..4de4ed6 100644 --- a/library/src/main/res/layout/kau_search_item.xml +++ b/library/src/main/res/layout/kau_search_item.xml @@ -1,5 +1,6 @@ - + android:scaleType="centerInside" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + android:textSize="@dimen/kau_search_text_small" + app:layout_constraintStart_toEndOf="@id/search_icon" + app:layout_constraintTop_toTopOf="parent" /> - \ No newline at end of file + + + \ No newline at end of file diff --git a/library/src/main/res/values/dimens_search.xml b/library/src/main/res/values/dimens_search.xml index 9d4ea5e..acf79cb 100644 --- a/library/src/main/res/values/dimens_search.xml +++ b/library/src/main/res/values/dimens_search.xml @@ -13,6 +13,7 @@ 56dp 56dp 24dp + 12sp 14sp 16sp 24dp -- cgit v1.2.3