aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Wang <allanwang@google.com>2020-01-14 14:48:40 -0800
committerAllan Wang <allanwang@google.com>2020-01-14 14:48:40 -0800
commit71232a0547742d924d05f3bffd0ec6657e154b94 (patch)
treef60acf51619fcdebb04088d12a7e4a00047693d4
parentf24a2cfb20d86b6dae8aa9ccf16eb4d038955874 (diff)
downloadkau-71232a0547742d924d05f3bffd0ec6657e154b94.tar.gz
kau-71232a0547742d924d05f3bffd0ec6657e154b94.tar.bz2
kau-71232a0547742d924d05f3bffd0ec6657e154b94.zip
Add unbounded height attribute
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt253
1 files changed, 131 insertions, 122 deletions
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 4757a00..07c2cee 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
@@ -50,25 +50,25 @@ import kotlin.math.max
@KauUtils
inline fun <T : View> T.visible(): T {
- visibility = View.VISIBLE
- return this
+ visibility = View.VISIBLE
+ return this
}
@KauUtils
inline fun <T : View> T.invisible(): T {
- visibility = View.INVISIBLE
- return this
+ visibility = View.INVISIBLE
+ return this
}
@KauUtils
inline fun <T : View> T.gone(): T {
- visibility = View.GONE
- return this
+ visibility = View.GONE
+ return this
}
@KauUtils
inline fun <T : View> T.invisibleIf(invisible: Boolean): T =
- if (invisible) invisible() else visible()
+ if (invisible) invisible() else visible()
@KauUtils
inline fun <T : View> T.visibleIf(visible: Boolean): T = if (visible) visible() else gone()
@@ -78,55 +78,64 @@ inline fun <T : View> T.goneIf(gone: Boolean): T = visibleIf(!gone)
@KauUtils
inline val View.isVisible: Boolean
- get() = visibility == View.VISIBLE
+ get() = visibility == View.VISIBLE
@KauUtils
inline val View.isInvisible: Boolean
- get() = visibility == View.INVISIBLE
+ get() = visibility == View.INVISIBLE
@KauUtils
inline val View.isGone: Boolean
- get() = visibility == View.GONE
+ get() = visibility == View.GONE
+
+/**
+ * Measure the height of a view if it had match_parent for width and no height restrictions
+ */
+inline val View.unboundedHeight: Int
+ get() {
+ measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
+ return measuredHeight
+ }
@KauUtils
inline fun View.setBackgroundColorRes(@ColorRes color: Int) =
- setBackgroundColor(context.color(color))
+ setBackgroundColor(context.color(color))
fun View.snackbar(
- text: String,
- duration: Int = Snackbar.LENGTH_LONG,
- builder: Snackbar.() -> Unit = {}
+ text: String,
+ duration: Int = Snackbar.LENGTH_LONG,
+ builder: Snackbar.() -> Unit = {}
): Snackbar {
- val snackbar = Snackbar.make(this, text, duration)
- snackbar.builder()
- snackbar.show()
- return snackbar
+ val snackbar = Snackbar.make(this, text, duration)
+ snackbar.builder()
+ snackbar.show()
+ return snackbar
}
fun View.snackbar(
- @StringRes textId: Int,
- duration: Int = Snackbar.LENGTH_LONG,
- builder: Snackbar.() -> Unit = {}
+ @StringRes textId: Int,
+ duration: Int = Snackbar.LENGTH_LONG,
+ builder: Snackbar.() -> Unit = {}
) =
- snackbar(context.string(textId), duration, builder)
+ snackbar(context.string(textId), duration, builder)
@KauUtils
fun ImageView.setIcon(
- icon: IIcon?,
- sizeDp: Int = 24,
- @ColorInt color: Int = Color.WHITE,
- builder: IconicsDrawable.() -> Unit = {}
+ icon: IIcon?,
+ sizeDp: Int = 24,
+ @ColorInt color: Int = Color.WHITE,
+ builder: IconicsDrawable.() -> Unit = {}
) {
- icon ?: return
- setImageDrawable(icon.toDrawable(context, sizeDp = sizeDp, color = color, builder = builder))
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- imageTintList = ColorStateList.valueOf(color)
- }
+ icon ?: return
+ setImageDrawable(icon.toDrawable(context, sizeDp = sizeDp, color = color, builder = builder))
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ imageTintList = ColorStateList.valueOf(color)
+ }
}
@KauUtils
inline val FloatingActionButton.isHidden
- get() = !isShown
+ get() = !isShown
fun FloatingActionButton.showIf(show: Boolean) = if (show) show() else hide()
@@ -134,7 +143,7 @@ fun FloatingActionButton.hideIf(hide: Boolean) = if (hide) hide() else show()
@KauUtils
fun ViewGroup.inflate(layoutId: Int, attachToRoot: Boolean = false): View =
- LayoutInflater.from(context).inflate(layoutId, this, attachToRoot)
+ LayoutInflater.from(context).inflate(layoutId, this, attachToRoot)
/**
* Set left margin to a value in px
@@ -184,14 +193,14 @@ fun View.setMargin(margin: Int) = setMargins(margin, KAU_ALL)
*/
@KauUtils
private fun View.setMargins(margin: Int, flag: Int): Boolean {
- val p = (layoutParams as? ViewGroup.MarginLayoutParams) ?: return false
- p.setMargins(
- if (flag and KAU_LEFT > 0) margin else p.leftMargin,
- if (flag and KAU_TOP > 0) margin else p.topMargin,
- if (flag and KAU_RIGHT > 0) margin else p.rightMargin,
- if (flag and KAU_BOTTOM > 0) margin else p.bottomMargin
- )
- return true
+ val p = (layoutParams as? ViewGroup.MarginLayoutParams) ?: return false
+ p.setMargins(
+ if (flag and KAU_LEFT > 0) margin else p.leftMargin,
+ if (flag and KAU_TOP > 0) margin else p.topMargin,
+ if (flag and KAU_RIGHT > 0) margin else p.rightMargin,
+ if (flag and KAU_BOTTOM > 0) margin else p.bottomMargin
+ )
+ return true
}
/**
@@ -241,41 +250,41 @@ fun View.setPadding(padding: Int) = setPadding(padding, KAU_ALL)
*/
@KauUtils
private fun View.setPadding(padding: Int, flag: Int) {
- setPadding(
- if (flag and KAU_LEFT > 0) padding else paddingLeft,
- if (flag and KAU_TOP > 0) padding else paddingTop,
- if (flag and KAU_RIGHT > 0) padding else paddingRight,
- if (flag and KAU_BOTTOM > 0) padding else paddingBottom
- )
+ setPadding(
+ if (flag and KAU_LEFT > 0) padding else paddingLeft,
+ if (flag and KAU_TOP > 0) padding else paddingTop,
+ if (flag and KAU_RIGHT > 0) padding else paddingRight,
+ if (flag and KAU_BOTTOM > 0) padding else paddingBottom
+ )
}
@KauUtils
fun View.hideKeyboard() {
- clearFocus()
- (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(
- windowToken,
- 0
- )
+ clearFocus()
+ (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(
+ windowToken,
+ 0
+ )
}
@KauUtils
fun View.showKeyboard() {
- requestFocus()
- (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).showSoftInput(
- this,
- InputMethodManager.SHOW_IMPLICIT
- )
+ requestFocus()
+ (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).showSoftInput(
+ this,
+ InputMethodManager.SHOW_IMPLICIT
+ )
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
@KauUtils
fun View.setRippleBackground(@ColorInt foregroundColor: Int, @ColorInt backgroundColor: Int) {
- background = createSimpleRippleDrawable(foregroundColor, backgroundColor)
+ background = createSimpleRippleDrawable(foregroundColor, backgroundColor)
}
@KauUtils
inline val View.parentViewGroup: ViewGroup
- get() = parent as ViewGroup
+ get() = parent as ViewGroup
inline val EditText.value: String get() = text.toString().trim()
@@ -285,28 +294,28 @@ inline val TextInputEditText.value: String get() = text.toString().trim()
* Generates a recycler view with match parent and a linearlayoutmanager, since it's so commonly used
*/
fun Context.fullLinearRecycler(
- rvAdapter: RecyclerView.Adapter<*>? = null,
- configs: RecyclerView.() -> Unit = {}
+ rvAdapter: RecyclerView.Adapter<*>? = null,
+ configs: RecyclerView.() -> Unit = {}
) =
- RecyclerView(this).apply {
- layoutManager = LinearLayoutManager(this@fullLinearRecycler)
- layoutParams =
- RecyclerView.LayoutParams(
- RecyclerView.LayoutParams.MATCH_PARENT,
- RecyclerView.LayoutParams.MATCH_PARENT
- )
- if (rvAdapter != null) {
- adapter = rvAdapter
- }
- configs()
+ RecyclerView(this).apply {
+ layoutManager = LinearLayoutManager(this@fullLinearRecycler)
+ layoutParams =
+ RecyclerView.LayoutParams(
+ RecyclerView.LayoutParams.MATCH_PARENT,
+ RecyclerView.LayoutParams.MATCH_PARENT
+ )
+ if (rvAdapter != null) {
+ adapter = rvAdapter
}
+ configs()
+ }
/**
* Sets a linear layout manager along with an adapter
*/
fun RecyclerView.withLinearAdapter(rvAdapter: RecyclerView.Adapter<*>) = apply {
- layoutManager = LinearLayoutManager(context)
- adapter = rvAdapter
+ layoutManager = LinearLayoutManager(context)
+ adapter = rvAdapter
}
/**
@@ -315,28 +324,28 @@ fun RecyclerView.withLinearAdapter(rvAdapter: RecyclerView.Adapter<*>) = apply {
* If it is already shown, scaling and alpha animations will be added to the action
*/
inline fun <T : ImageView> T.fadeScaleTransition(
- duration: Long = 500L,
- minScale: Float = 0.7f,
- crossinline action: T.() -> Unit
+ 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 {
- this.duration = duration
- addUpdateListener {
- val x = it.animatedValue as Float
- scaleXY = x * (1 - minScale) + minScale
- imageAlpha = (x * 255).toInt()
- if (it.animatedFraction > 0.5f && !transitioned) {
- transitioned = true
- action()
- }
- }
- start()
+ if (!isVisible) {
+ action()
+ } else {
+ var transitioned = false
+ ValueAnimator.ofFloat(1.0f, 0.0f, 1.0f).apply {
+ this.duration = duration
+ addUpdateListener {
+ val x = it.animatedValue as Float
+ scaleXY = x * (1 - minScale) + minScale
+ imageAlpha = (x * 255).toInt()
+ if (it.animatedFraction > 0.5f && !transitioned) {
+ transitioned = true
+ action()
}
+ }
+ start()
}
+ }
}
/**
@@ -344,45 +353,45 @@ inline fun <T : ImageView> T.fadeScaleTransition(
* The fab will reappear when scrolling has stopped or if the user scrolls up
*/
fun FloatingActionButton.hideOnDownwardsScroll(recycler: RecyclerView) {
- recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
+ recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
- override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
- if (newState == RecyclerView.SCROLL_STATE_IDLE && !isShown) {
- show()
- }
- }
+ override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
+ if (newState == RecyclerView.SCROLL_STATE_IDLE && !isShown) {
+ show()
+ }
+ }
- override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
- if (dy > 0 && isShown) {
- hide()
- } else if (dy < 0 && isHidden) {
- show()
- }
- }
- })
+ override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
+ if (dy > 0 && isShown) {
+ hide()
+ } else if (dy < 0 && isHidden) {
+ show()
+ }
+ }
+ })
}
inline var View.scaleXY
- get() = max(scaleX, scaleY)
- set(value) {
- scaleX = value
- scaleY = value
- }
+ get() = 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
- }
+ 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
}
+ }
}