Updated on 2026-08-14

This commit is contained in:
Tangem 2023-02-13 18:13:13 +03:00
parent 545932dca3
commit da4a76eff1
4 changed files with 36 additions and 63 deletions

View file

@ -1,54 +1,47 @@
package com.tangem.core.ui.components
import android.graphics.Rect
import android.view.ViewTreeObserver
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.exclude
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
sealed class Keyboard {
data class Opened(val height: Int) : Keyboard()
object Closed : Keyboard()
sealed interface Keyboard {
val height: Dp
data class Opened(override val height: Dp) : Keyboard
object Closed : Keyboard {
override val height: Dp = 0.dp
}
}
/**
* Allows to subscribe to a soft keyboard to detect when it's open/closed
*/
@Suppress("MagicNumber")
@Deprecated("Use Modifier.imePadding() on pure Compose screens (without XML layouts)")
@Composable
fun keyboardAsState(): State<Keyboard> {
val keyboardState: MutableState<Keyboard> = remember { mutableStateOf(Keyboard.Closed) }
val view = LocalView.current
val discrepancy = remember {
mutableStateOf(0)
}
DisposableEffect(view) {
val onGlobalListener = ViewTreeObserver.OnGlobalLayoutListener {
val rect = Rect()
view.getWindowVisibleDisplayFrame(rect)
val screenHeight = view.rootView.height
val keypadHeight: Int = screenHeight - (rect.bottom + rect.top) - discrepancy.value
if (discrepancy.value == 0) {
discrepancy.value = keypadHeight
if (keypadHeight == 0) discrepancy.value = 1
}
val density = LocalDensity.current
val imeInsets = WindowInsets.ime
.exclude(WindowInsets.navigationBars)
.getBottom(density)
keyboardState.value = if (keypadHeight > screenHeight * 0.15) {
Keyboard.Opened(keypadHeight)
return remember(imeInsets) {
derivedStateOf {
if (imeInsets > 0) {
Keyboard.Opened(
height = with(density) { imeInsets.toDp() },
)
} else {
Keyboard.Closed
}
}
view.viewTreeObserver.addOnGlobalLayoutListener(onGlobalListener)
onDispose {
view.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalListener)
}
}
return keyboardState
}