如何使用 Jetpack Compose 显示键盘?

问题描述 投票:0回答:7

如何滑入键盘? 我试过:

val keyboardController: SoftwareKeyboardController? = LocalSoftwareKeyboardController.current
  keyboardController?.show()

但这不起作用。我缺少什么?也许一些清单标志?

android-jetpack-compose android-jetpack android-windowmanager android-window
7个回答
26
投票

要在 Compose 中显示键盘:

val showKeyboard = remember { mutableStateOf(true) }
val focusRequester = remember { FocusRequester() }
val keyboard = LocalSoftwareKeyboardController.current

OutlinedTextField(
    modifier = Modifier
            .fillMaxWidth()
            .focusRequester(focusRequester),
    value = value,
    textStyle = MaterialTheme.typography.body2,
    onValueChange = { onValueChange(it)},
    label = { Text(label) }
)

// LaunchedEffect prevents endless focus request
LaunchedEffect(focusRequester) {
    if (showKeyboard.equals(true)) {
        focusRequester.requestFocus()
        delay(100) // Make sure you have delay here
        keyboard?.show()
    }
}

17
投票

delay
不是显示键盘的可靠方法。键盘未显示,因为在大多数情况下窗口尚未获得焦点。解决方案是这样的:

val windowInfo = LocalWindowInfo.current
val focusRequester = remember { FocusRequester() }
TextField(modifier = Modifier.focusRequester(focusRequester)...)

LaunchedEffect(windowInfo) {
     snapshotFlow { windowInfo.isWindowFocused }.collect { isWindowFocused ->
         if (isWindowFocused) {
             focusRequester.requestFocus()
         }
     }
}

9
投票

我目前使用的是 compose BOM 版本

2023.05.01

其他答案对我不起作用。然而,当我从接受的答案中更改 LaunchedEffect 时,我确实设法让它工作。使用以下代码片段,软件键盘将打开,您可以开始在文本字段内输入内容。

val focusRequester = remember { FocusRequester() }

OutlinedTextField(
    modifier = Modifier
            .fillMaxWidth()
            .focusRequester(focusRequester),
    value = value,
    textStyle = MaterialTheme.typography.body2,
    onValueChange = { onValueChange(it)},
    label = { Text(label) }
)

LaunchedEffect(focusRequester) {
   awaitFrame()
   focusRequester.requestFocus()
}

2
投票

对于我的用例,当底部工作表显示有 editText 时,我需要显示键盘。接受的答案第一次有效,然后如果用户切换到不同的应用程序一段时间(中断)则停止工作。因此,我将上述解决方案与生命周期事件结合起来,以在视图实际上对用户可见时触发键盘。

fun SomeView(lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current) {
 val focusRequester = remember { FocusRequester() }
 val keyboard = LocalSoftwareKeyboardController.current
 val scope = rememberCoroutineScope()


 DisposableEffect(key1 = lifecycleOwner, effect = {

       val observer = LifecycleEventObserver { _, event ->

           scope.launch {
               if (event == Lifecycle.Event.ON_RESUME) {
                   focusRequester.requestFocus()
                   awaitFrame()
                   keyboard?.show()
               }
           }
       }

       // Add the observer to the lifecycle
       lifecycleOwner.lifecycle.addObserver(observer)

       onDispose {
           lifecycleOwner.lifecycle.removeObserver(observer)
       }
   })


         TextField(
            modifier = Modifier
                .fillMaxWidth()
                .focusRequester(focusRequester),
            value = "",
            onValueChange = {},
            placeholder = { Text(text = "New Note") },
            colors = TextFieldDefaults.textFieldColors(
                backgroundColor = Color.Transparent,
            )
        )

上面添加了一个生命周期观察者,并在生命周期事件为

ON_RESUME
时触发键盘显示。


1
投票

当场景打开时需要显示键盘进行编辑时,以下方法可以正常工作:

    val focusRequester = remember { FocusRequester() }
    LaunchedEffect(Unit) { focusRequester.requestFocus() }

    TextField(
        ...
        modifier = Modifier
           .fillMaxWidth()
           .focusRequester(focusRequester),
    )

-1
投票

Leon Wu 的答案https://stackoverflow.com/a/75985103/4908512似乎是最好的答案。对于我的用例,最好将请求焦点放在副作用中。

val focusRequester = remember {
    FocusRequester()
}
var queryText by remember(query) { mutableStateOf(query) }

val scope = rememberCoroutineScope()
val windowInfo = LocalWindowInfo.current

SideEffect {
    scope.launch {
        snapshotFlow { windowInfo.isWindowFocused }.collect { isWindowFocused ->
            if (isWindowFocused && requestFocus) {
                focusRequester.requestFocus()
            }
        }
    }
}
TextField(modifier = Modifier.focusRequester(focusRequester)...)

-12
投票

这是使用基于视图的官方方法的快速破解,但我们通过使用互操作性 API 来使用 Compose。

fun showSoftKeyboard(view: View) {
    if (view.requestFocus()) {
        val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
    }
}

阅读更多这里

并传递一个空的可组合项(视图)作为参数:

showSoftKeyboard(AndroidView(context))
© www.soinside.com 2019 - 2024. All rights reserved.