首页 > 解决方案 > 如何在关闭键盘时清除 TextField 焦点并防止在 Jetpack Compose 中退出应用程序所需的两次后按?

问题描述

我正在使用 BasicTextField。

当我开始编辑时,后退按钮变为隐藏键盘按钮(向下箭头)。

首先按下后退按钮隐藏键盘,但焦点仍在文本字段上。onFocusChanged和处理程序都BackPressHandler没有被调用。

第二次按下后退按钮清除焦点:onFocusChanged被调用和BackPressHandler未被调用。

BackHandler {
    println("BackPressHandler")
}
val valueState = remember { mutableStateOf(TextFieldValue(text = "")) }
BasicTextField(
    value = valueState.value,
    onValueChange = {
        valueState.value = it
    },
    modifier = Modifier
        .fillMaxWidth()
        .onFocusChanged {
            println("isFocused ${it.isFocused}")
        }
)

第三次 BackHandler 工作正常。只是用于测试,我不应该在这里需要它,它预计在第一次后退按钮点击后焦点会丢失

标签: androidandroid-jetpack-composeandroid-jetpack-compose-text

解决方案


当键盘隐藏时,聚焦文本字段存在撰写问题,阻止后退按钮关闭应用程序。它被标记为已修复,但将包含在未来的某个版本中,而不是1.0

但是,据我了解,在键盘被关闭后文本字段没有失去焦点的事实是 Android 上的预期行为(因为可能连接了键盘?我没有得到原因)。这也是它在旧的 android 布局中的工作方式

这对我来说似乎很奇怪,所以我使用了以下修饰符,当键盘消失时它会放弃焦点:

fun Modifier.clearFocusOnKeyboardDismiss(): Modifier = composed {
    var isFocused by remember { mutableStateOf(false) }
    var keyboardAppearedSinceLastFocused by remember { mutableStateOf(false) }
    if (isFocused) {
        val imeIsVisible = LocalWindowInsets.current.ime.isVisible
        val focusManager = LocalFocusManager.current
        LaunchedEffect(imeIsVisible) {
            if (imeIsVisible) {
                keyboardAppearedSinceLastFocused = true
            } else if (keyboardAppearedSinceLastFocused) {
                focusManager.clearFocus()
            }
        }
    }
    onFocusEvent {
        if (isFocused != it.isFocused) {
            isFocused = it.isFocused
            if (isFocused) {
                keyboardAppearedSinceLastFocused = false
            }
        }
    }
}

ps 你需要安装accompanist insets依赖LocalWindowInsets.current.ime

用法:

BasicTextField(
    value = valueState.value,
    onValueChange = {
        valueState.value = it
    },
    modifier = Modifier
        .clearFocusOnKeyboardDismiss()
)

推荐阅读