package exh.util import android.view.View import android.view.ViewGroup import android.view.WindowInsets import android.widget.FrameLayout import androidx.annotation.Px inline val View.marginTop: Int get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.topMargin ?: 0 inline val View.marginBottom: Int get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.bottomMargin ?: 0 inline val View.marginRight: Int get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.rightMargin ?: 0 inline val View.marginLeft: Int get() = (layoutParams as? ViewGroup.MarginLayoutParams)?.leftMargin ?: 0 fun View.doOnApplyWindowInsets(f: (View, WindowInsets, ViewPaddingState) -> Unit) { // Create a snapshot of the view's padding state val paddingState = createStateForView(this) setOnApplyWindowInsetsListener { v, insets -> f(v, insets, paddingState) insets } requestApplyInsetsWhenAttached() } object ControllerViewWindowInsetsListener : View.OnApplyWindowInsetsListener { override fun onApplyWindowInsets(v: View, insets: WindowInsets): WindowInsets { v.updateLayoutParams { val attrsArray = intArrayOf(android.R.attr.actionBarSize) val array = v.context.obtainStyledAttributes(attrsArray) topMargin = insets.systemWindowInsetTop + array.getDimensionPixelSize(0, 0) array.recycle() } return insets } } fun View.requestApplyInsetsWhenAttached() { if (isAttachedToWindow) { requestApplyInsets() } else { addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View) { v.requestApplyInsets() } override fun onViewDetachedFromWindow(v: View) = Unit }) } } inline fun View.updateLayoutParams(block: T.() -> Unit) { val params = layoutParams as T block(params) layoutParams = params } fun View.applyWindowInsetsForController() { setOnApplyWindowInsetsListener(ControllerViewWindowInsetsListener) requestApplyInsetsWhenAttached() } inline fun View.updatePaddingRelative( @Px start: Int = paddingStart, @Px top: Int = paddingTop, @Px end: Int = paddingEnd, @Px bottom: Int = paddingBottom ) { setPaddingRelative(start, top, end, bottom) } private fun createStateForView(view: View) = ViewPaddingState( view.paddingLeft, view.paddingTop, view.paddingRight, view.paddingBottom, view.paddingStart, view.paddingEnd ) data class ViewPaddingState( val left: Int, val top: Int, val right: Int, val bottom: Int, val start: Int, val end: Int ) object RecyclerWindowInsetsListener : View.OnApplyWindowInsetsListener { override fun onApplyWindowInsets(v: View, insets: WindowInsets): WindowInsets { v.updatePaddingRelative(bottom = insets.systemWindowInsetBottom) // v.updatePaddingRelative(bottom = v.paddingBottom + insets.systemWindowInsetBottom) return insets } }