防止键盘出现在 Jetpack Compose 应用程序中

Vit*_*mos 9 android android-jetpack-compose

我正在制作一个计算器来学习 Compose,因此我在屏幕上放置了自己的数字按钮,并且我想防止软键盘出现。

这是我的仓库: https: //github.com/vitor-ramos/CalculadorCompose

我注意到 TextFieldImpl.kt 中有一个修饰符来显示键盘,所以我尝试克隆代码并删除该行:keyboardController.value?.showSoftwareKeyboard()我知道复制这样的代码不是一个好主意,但我想尝试一下,并且它不起作用。正如您在下面的原始代码中看到的,有一个 TODO 说它应该由 BaseTextField 处理,但我查看了它的代码,没有找到它显示或隐藏键盘的位置。

val textFieldModifier = modifier
    .focusRequester(focusRequester)
    .focusObserver { isFocused = it.isFocused }
    .clickable(indication = null) {
        focusRequester.requestFocus()
        // TODO(b/163109449): Showing and hiding keyboard should be handled by BaseTextField.
        //  The requestFocus() call here should be enough to trigger the software keyboard.
        //  Investiate why this is needed here. If it is really needed, instead of doing
        //  this in the onClick callback, we should move this logic to the focusObserver
        //  so that it can show or hide the keyboard based on the focus state.
        keyboardController.value?.showSoftwareKeyboard()
    }
Run Code Online (Sandbox Code Playgroud)

我在这个问题中发现,通过视图我可以扩展 EditText 并更改功能,但我还没有找到 Compose 的等效项:Android: Disable soft Keyboard at all EditTexts

public class NoImeEditText extends EditText {
    public NoImeEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    public boolean onCheckIsTextEditor() {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 25

我已经测试了 Arun Pdiyan 解决方案,并且像带有 null LocalTextInputService 的魅力一样工作(在我的例子中,我从设备连接的条形码阅读器读取数据)

 CompositionLocalProvider(
        LocalTextInputService provides null
    ) {
        TextField(
            value = barcodeReaderService.readedText.value,
            onValueChange = { textState.value=it },
            label = { Text("The Label") }
        )
    }
Run Code Online (Sandbox Code Playgroud)


Cem*_*mal 5

您可以通过向 TextField 提供 TextInputService 来隐藏撰写时的键盘。您可以实现 TextInputService 或仅将其传递为 null 以禁用输入服务。

CompositionLocalProvider(
  // You can also provides null to completely disable the default input service.
  LocalTextInputService provides myTextInputService 
) {
  BaseTextField(...)
}
Run Code Online (Sandbox Code Playgroud)

您可能会在这里看到谷歌员工关于此主题的回答。


Cae*_*lis 4

解释

我创建了一个 Composable ReadonlyTextField,它在文本字段前面放置了一个不可见的框。该框的大小与文本字段相同。

使用该解决方法,您将无法再将文本字段聚焦,因此不会出现键盘。为了应用自定义点击处理,我onClick向框修改器添加了一个。

这并不是一个真正干净的解决方案,而是一个很好的解决方法。

ReadonlyTextField 的实现

@Composable
fun ReadonlyTextField(
    value: TextFieldValue,
    onValueChange: (TextFieldValue) -> Unit,
    modifier: Modifier = Modifier,
    onClick: () -> Unit,
    label: @Composable () -> Unit
) {

    Box {
        TextField(
            value = value,
            onValueChange = onValueChange,
            modifier = modifier,
            label = label
        )

        Box(
            modifier = Modifier
                .matchParentSize()
                .alpha(0f)
                .clickable(onClick = onClick),
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

ReadonlyTextField 的用法

@Composable
fun App() {
    val textState = remember { mutableStateOf(TextFieldValue()) }

    Column {
        ReadonlyTextField(
            value = textState.value,
            onValueChange = { textState.value = it },
            onClick = {
                // custom click handling (e.g. open dialog)
            },
            label = {
                Text(text = "Keyboardless Input")
            }
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

完整的集成示例可以在我的媒体帖子中找到: https ://caelis.medium.com/jetpack-compose-datepicker-textfield-39808e42646a

学分也转到这个 stackoverflow 答案: Jetpack Compose:禁用与 TextField 的交互