new*_*our 39 android-jetpack-compose
我在撰写中发现的唯一方法是使用accompanist-insetsand 删除窗口插图。这会导致我的应用程序布局出现其他问题。
Android 方式似乎是这样的,我可以将其传递到我的撰写应用程序中并采取相应的操作。
jetpack compose 还有其他方法吗?
uji*_*zin 105
有了新的WindowInsetsAPI,事情变得更容易
首先,要返回正确的值,您需要设置:
WindowCompat.setDecorFitsSystemWindows(window, false)
Run Code Online (Sandbox Code Playgroud)
然后使用键盘作为状态:
@Composable
fun keyboardAsState(): State<Boolean> {
val isImeVisible = WindowInsets.ime.getBottom(LocalDensity.current) > 0
return rememberUpdatedState(isImeVisible)
}
Run Code Online (Sandbox Code Playgroud)
使用示例:
val isKeyboardOpen by keyboardAsState() // true or false
Run Code Online (Sandbox Code Playgroud)
ps:我尝试使用 WindowInsets.isImeVisible,但它在第一次调用中返回 true。
如果你想要声明,我找到了这个解决方案:
WindowCompat.setDecorFitsSystemWindows(window, false)
Run Code Online (Sandbox Code Playgroud)
要检测/检查该值,您只需要这样:
@Composable
fun keyboardAsState(): State<Boolean> {
val isImeVisible = WindowInsets.ime.getBottom(LocalDensity.current) > 0
return rememberUpdatedState(isImeVisible)
}
Run Code Online (Sandbox Code Playgroud)
Sty*_*pox 27
这是一个解决方案,用于OnGlobalLayoutListener监听布局的更改并使用新的窗口插入 API来执行计算,如文档所建议的。您可以将此代码放置在@Composable函数内的任何位置并isKeyboardOpen根据需要进行处理。我测试过,它适用于API 21及更高版本。
val view = LocalView.current
val viewTreeObserver = view.viewTreeObserver
DisposableEffect(viewTreeObserver) {
val listener = ViewTreeObserver.OnGlobalLayoutListener {
val isKeyboardOpen = ViewCompat.getRootWindowInsets(view)
?.isVisible(WindowInsetsCompat.Type.ime()) ?: true
// ... do anything you want here with `isKeyboardOpen`
}
viewTreeObserver.addOnGlobalLayoutListener(listener)
onDispose {
viewTreeObserver.removeOnGlobalLayoutListener(listener)
}
}
Run Code Online (Sandbox Code Playgroud)
对我来说,其他解决方案效果不佳:键盘将始终关闭。
OnGlobalLayoutListener基于 - 的答案中,所使用的公式似乎没有发挥应有的作用,并且使用了旧的 API 。WindowInsetListener基于 - 的答案中,由于view不是根视图,因此不会对其应用窗口插入。我尝试替换view为view.rootView,尽管键盘检测代码可以工作,但传递根视图来setOnApplyWindowInsetsListener替换组件设置的任何侦听器,这显然是不需要的。要在不更改 Activity 中的设置的情况下处理 Jetpack Compose 中的键盘打开和关闭行为WindowCompat.setDecorFitsSystemWindows(window, false),尤其是在使用包含 Fragments 和 Composables 的单个 Activity 架构时,您可以使用以下方法:
@Composable
fun keyboardAsState(): State<Boolean> {
val view = LocalView.current
var isImeVisible by remember { mutableStateOf(false) }
DisposableEffect(LocalWindowInfo.current) {
val listener = ViewTreeObserver.OnPreDrawListener {
isImeVisible = ViewCompat.getRootWindowInsets(view)
?.isVisible(WindowInsetsCompat.Type.ime()) == true
true
}
view.viewTreeObserver.addOnPreDrawListener(listener)
onDispose {
view.viewTreeObserver.removeOnPreDrawListener(listener)
}
}
return rememberUpdatedState(isImeVisible)
}
Run Code Online (Sandbox Code Playgroud)
此代码片段提供了一个可组合函数keyboardAsState,允许您观察并响应键盘可见状态的变化。它通过利用DisposableEffect和ViewTreeObserver.OnPreDrawListener来检测键盘何时打开或关闭来实现这一点。
要使用此函数,只需在val isKeyboardOpen by keyboardAsState()需要跟踪键盘状态的可组合项中访问其值即可。它将返回State<Boolean>反映键盘当前是否可见的 a 。
我找到了一种使用 Android 的方法viewTreeObserver。它本质上是 Android 版本,但它调用了可在 compose 中使用的回调。
class MainActivity : ComponentActivity() {
var kbGone = false
var kbOpened: () -> Unit = {}
var kbClosed: () -> Unit = {}
override fun onCreate(state: Bundle?) {
super.onCreate(state)
setContent {
kbClosed = {
// dismiss the keyboard with LocalFocusManager for example
}
kbOpened = {
// something
}
MyComponent()
}
setupKeyboardDetection(findViewById<View>(android.R.id.content))
}
fun setupKeyboardDetection(contentView: View) {
contentView.viewTreeObserver.addOnGlobalLayoutListener {
val r = Rect()
contentView.getWindowVisibleDisplayFrame(r)
val screenHeight = contentView.rootView.height
val keypadHeight = screenHeight - r.bottom
if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
kbGone = false
kbOpened()
} else(!kbGone) {
kbGone = true
kbClosed()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
23507 次 |
| 最近记录: |