Better insets propagation.

This commit is contained in:
Alex Hart
2025-11-12 15:46:58 -04:00
parent dd8104bf61
commit baf3309a04
6 changed files with 27 additions and 139 deletions

View File

@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.components
import android.content.Context
import android.content.res.Configuration
import android.util.AttributeSet
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.Guideline
import androidx.core.content.withStyledAttributes
@@ -14,9 +13,7 @@ import androidx.core.view.WindowInsetsCompat
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.main.VerticalInsets
import org.thoughtcrime.securesms.util.ViewUtil
import kotlin.math.roundToInt
/**
* A specialized [ConstraintLayout] that sets guidelines based on the window insets provided
@@ -62,11 +59,10 @@ open class InsetAwareConstraintLayout @JvmOverloads constructor(
private val keyboardAnimator = KeyboardInsetAnimator()
private var overridingKeyboard: Boolean = false
private var previousKeyboardHeight: Int = 0
private var applyRootInsets: Boolean = false
private var previousStatusBarInset: Int = 0
private var insets: WindowInsetsCompat? = null
private var windowTypes: Int = InsetAwareConstraintLayout.windowTypes
private var verticalInsetOverride: VerticalInsets = VerticalInsets.Zero
private val windowInsetsListener = androidx.core.view.OnApplyWindowInsetsListener { _, insets ->
this.insets = insets
@@ -80,39 +76,25 @@ open class InsetAwareConstraintLayout @JvmOverloads constructor(
override fun onAttachedToWindow() {
super.onAttachedToWindow()
ViewCompat.setOnApplyWindowInsetsListener(insetTarget(), windowInsetsListener)
ViewCompat.setOnApplyWindowInsetsListener(this, windowInsetsListener)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
ViewCompat.setOnApplyWindowInsetsListener(insetTarget(), null)
ViewCompat.setOnApplyWindowInsetsListener(this, null)
}
init {
if (attrs != null) {
context.withStyledAttributes(attrs, R.styleable.InsetAwareConstraintLayout) {
applyRootInsets = getBoolean(R.styleable.InsetAwareConstraintLayout_applyRootInsets, false)
if (getBoolean(R.styleable.InsetAwareConstraintLayout_animateKeyboardChanges, false)) {
ViewCompat.setWindowInsetsAnimationCallback(insetTarget(), keyboardAnimator)
ViewCompat.setWindowInsetsAnimationCallback(this@InsetAwareConstraintLayout, keyboardAnimator)
}
}
}
}
private fun insetTarget(): View = if (applyRootInsets) rootView else this
fun setApplyRootInsets(useRootInsets: Boolean) {
if (applyRootInsets == useRootInsets) {
return
}
ViewCompat.setOnApplyWindowInsetsListener(insetTarget(), null)
applyRootInsets = useRootInsets
ViewCompat.setOnApplyWindowInsetsListener(insetTarget(), windowInsetsListener)
}
/**
* Specifies whether or not window insets should be accounted for when applying
* insets. This is useful when choosing whether to display the content in this
@@ -130,14 +112,6 @@ open class InsetAwareConstraintLayout @JvmOverloads constructor(
}
}
fun applyInsets(insets: VerticalInsets) {
verticalInsetOverride = insets
if (this.insets != null) {
applyInsets(this.insets!!.getInsets(windowTypes), this.insets!!.getInsets(keyboardType))
}
}
fun addKeyboardStateListener(listener: KeyboardStateListener) {
keyboardStateListeners += listener
}
@@ -157,18 +131,24 @@ open class InsetAwareConstraintLayout @JvmOverloads constructor(
private fun applyInsets(windowInsets: Insets, keyboardInsets: Insets) {
val isLtr = ViewUtil.isLtr(this)
val statusBar = if (verticalInsetOverride == VerticalInsets.Zero) windowInsets.top else verticalInsetOverride.statusBar.roundToInt()
val navigationBar = if (verticalInsetOverride == VerticalInsets.Zero) windowInsets.bottom else verticalInsetOverride.navBar.roundToInt()
val statusBar = windowInsets.top
val navigationBar = windowInsets.bottom
val parentStart = if (isLtr) windowInsets.left else windowInsets.right
val parentEnd = if (isLtr) windowInsets.right else windowInsets.left
statusBarGuideline?.setGuidelineBegin(statusBar)
navigationBarGuideline?.setGuidelineEnd(navigationBar)
parentStartGuideline?.setGuidelineBegin(parentStart)
parentEndGuideline?.setGuidelineEnd(parentEnd)
val statusBarShrinking = previousStatusBarInset > 0 && statusBar < previousStatusBarInset
windowInsetsListeners.forEach {
it.onApplyWindowInsets(statusBar, navigationBar, parentStart, parentEnd)
if (!statusBarShrinking) {
statusBarGuideline?.setGuidelineBegin(statusBar)
navigationBarGuideline?.setGuidelineEnd(navigationBar)
parentStartGuideline?.setGuidelineBegin(parentStart)
parentEndGuideline?.setGuidelineEnd(parentEnd)
windowInsetsListeners.forEach {
it.onApplyWindowInsets(statusBar, navigationBar, parentStart, parentEnd)
}
previousStatusBarInset = statusBar
}
if (keyboardInsets.bottom > 0) {