Skip to content

Instantly share code, notes, and snippets.

@JoaquimLey
Created June 12, 2019 13:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoaquimLey/dc827fb84ebbf5962277f3910ea54727 to your computer and use it in GitHub Desktop.
Save JoaquimLey/dc827fb84ebbf5962277f3910ea54727 to your computer and use it in GitHub Desktop.
/************************************************
* Insets Section *
************************************************/
/*******************
* Utility methods *
*******************/
fun View.applySystemBarPaddingInsets() {
this.doOnApplyWindowInsets { view, insets, padding, _ ->
view.updatePadding(top = padding.top + insets.systemWindowInsetTop)
}
}
fun View.applyNavigationBarPaddingInsets() {
this.doOnApplyWindowInsets { view, insets, padding, _ ->
view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom)
}
}
fun View.applyNavigationAndBottomNavigationViewMarginInsets() {
this.doOnApplyWindowInsets { view, insets, _, margin ->
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
setMargins(margin.left, margin.top, margin.right, margin.bottom + insets.systemWindowInsetBottom)
}
}
}
fun View.applyVerticalInsets() {
this.doOnApplyWindowInsets { view, windowInsets, initialPadding, _ ->
view.updatePadding(
top = initialPadding.top + windowInsets.systemWindowInsetTop,
bottom = initialPadding.bottom + windowInsets.systemWindowInsetBottom
)
}
}
/*********************
* Implementation(s) *
*********************/
fun View.doOnApplyWindowInsets(f: (View, WindowInsets, InitialPadding, InitialMargin) -> Unit) {
// Create a snapshot of the view's padding/margin state
val initialPadding = recordInitialPaddingForView(this)
val initialMargin = recordInitialMarginForView(this)
// Set an actual OnApplyWindowInsetsListener which proxies to the given
// lambda, also passing in the original padding state
setOnApplyWindowInsetsListener { v, insets ->
insets.consumeSystemWindowInsets()
f(v, insets, initialPadding, initialMargin)
// Always return the insets, so that children can also use them
insets
}
// request some insets
requestApplyInsetsWhenAttached()
}
class InitialPadding(
val left: Int, val top: Int,
val right: Int, val bottom: Int
)
class InitialMargin(
val left: Int, val top: Int,
val right: Int, val bottom: Int
)
private fun recordInitialPaddingForView(view: View) =
InitialPadding(view.paddingLeft, view.paddingTop, view.paddingRight, view.paddingBottom)
private fun recordInitialMarginForView(view: View) =
InitialMargin(
(view.layoutParams as? ViewGroup.MarginLayoutParams)?.leftMargin ?: 0,
(view.layoutParams as? ViewGroup.MarginLayoutParams)?.topMargin ?: 0,
(view.layoutParams as? ViewGroup.MarginLayoutParams)?.rightMargin ?: 0,
(view.layoutParams as? ViewGroup.MarginLayoutParams)?.bottomMargin ?: 0
)
private fun View.requestApplyInsetsWhenAttached() {
if (isAttachedToWindow) {
// We're already attached, just request as normal
requestApplyInsets()
} else {
// We're not attached to the hierarchy, add a listener to
// request when we are
addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
v.removeOnAttachStateChangeListener(this)
v.requestApplyInsets()
}
override fun onViewDetachedFromWindow(v: View) = Unit
})
}
}
@bes89
Copy link

bes89 commented Mar 3, 2020

Thanks for sharing!

@JoaquimLey
Copy link
Author

You are very welcome @bes89 ;)

There's a medium post up if you need more context / didn't come from it.

Cheers,

@Alesh17
Copy link

Alesh17 commented Jan 19, 2021

HI, you can change your recordInitialPaddingForView() and recordInitialMarginForView() to:

fun View.getPadding() = Rect(paddingLeft, paddingTop, paddingRight, paddingBottom)

fun View.getMargin() = Rect(marginLeft, marginTop, marginRight, marginBottom) 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment