简体   繁体   English

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

[英]Prevent the keyboard from appearing in a Jetpack Compose app

I'm making a calculator to learn Compose, so I placed my own number buttons on screen and I wanted to prevent the soft keyboard from appearing.我正在制作一个计算器来学习 Compose,所以我在屏幕上放置了自己的数字按钮,我想防止软键盘出现。

Here is my repo: https://github.com/vitor-ramos/CalculadorCompose这是我的回购: https : //github.com/vitor-ramos/CalculadorCompose

I noticed in TextFieldImpl.kt there is a modifier to show the keyboard, so I tried to clone the code and remove the line: keyboardController.value?.showSoftwareKeyboard() I know it's not a good idea to duplicate code like that, but I wanted to give it a try, and it didn't work.我注意到在 TextFieldImpl.kt 中有一个修饰符来显示键盘,所以我尝试克隆代码并删除该行: keyboardController.value?.showSoftwareKeyboard()我知道复制这样的代码不是一个好主意,但我想试一试,但没有成功。 As you can see in the original code below there's a TODO saying it should be handled by BaseTextField, but I looked in it's code and didn't find where it shows or hides the keyboard.正如您在下面的原始代码中看到的那样,有一个 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()
    }

I found in this question that with views I can extend EditText and change the functionality, but I haven't found a equivalent for Compose: Android: Disable soft keyboard at all EditTexts我在这个问题中发现,使用视图可以扩展 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;
    }
}

Explanation解释

I created a Composable ReadonlyTextField , that places a invisible box in front of the text field.我创建了一个 Composable ReadonlyTextField ,它在文本字段前面放置了一个不可见的框。 The box has the same size as the text field.该框的大小与文本字段的大小相同。

With that workaround you can't focus the text field anymore, so no keyboard appears.使用该解决方法,您无法再聚焦文本字段,因此不会出现键盘。 In order to apply custom click handling, i added a onClick to the Box-Modifier.为了应用自定义点击处理,我在 Box-Modifier 中添加了一个onClick

This is not really a clean solution, but a good workaround.这不是一个真正干净的解决方案,而是一个很好的解决方法。

Implementation of ReadonlyTextField 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),
        )
    }
}

Usage of ReadonlyTextField 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")
            }
        )
    }
}

A complete integrated example can be found in my medium post: https://caelis.medium.com/jetpack-compose-datepicker-textfield-39808e42646a一个完整的集成示例可以在我的媒体帖子中找到: https : //caelis.medium.com/jetpack-compose-datepicker-textfield-39808e42646a

Credits also go to this stackoverflow answer: Jetpack Compose: Disable Interaction with TextField积分也转到此 stackoverflow 答案: Jetpack Compose: Disable Interaction with TextField

With ReadonlyTextField it is not possible to position the cursor.使用 ReadonlyTextField 无法定位光标。 So added wrapped EditText inside a compose AndroidView所以在 compose AndroidView 中添加了包裹的 EditText

@Composable
fun NoKeyboardTextField(
    modifier: Modifier,
    text: String,
    textColor: Int
) {
    AndroidView(
        modifier = modifier,
        factory = { context ->
            AppCompatEditText(context).apply {
                isFocusable = true
                isFocusableInTouchMode = true
                showSoftInputOnFocus = false
            }
        },
        update = { view ->
            view.setText(text)
            view.setTextColor(textColor)
            view.setSelection(text.length)
        }
    )
}

You can hide keyboard on compose by providing TextInputService to TextField.您可以通过向 TextField 提供 TextInputService 来隐藏撰写时的键盘。 You can implement your TextInputService or just pass it null for disabling input service.您可以实现您的 TextInputService 或仅将其传递为 null 以禁用输入服务。

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

I have tested Arun Pdiyan solution and works like a charm with null LocalTextInputService (in my case I read data from device attached Barcode reader)我已经测试了 Arun Pdiyan 解决方案,并且使用 null LocalTextInputService 就像一个魅力(在我的情况下,我从设备连接的条形码阅读器读取数据)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在关闭键盘时清除 TextField 焦点并防止在 Jetpack Compose 中退出应用程序所需的两次后按? - How to clear TextField focus when closing the keyboard and prevent two back presses needed to exit app in Jetpack Compose? 如何从 Jetpack Compose TextField 关闭虚拟键盘? - How to close the virtual keyboard from a Jetpack Compose TextField? OutlinedTextField jetpack 在键盘后面组成 - OutlinedTextField jetpack compose behind the Keyboard Jetpack compose 避免键盘效应 - Jetpack compose avoid keyboard effect Android Jetpack Compose 键盘未关闭 - Android Jetpack Compose keyboard not close Jetpack Compose 中的 Android 键盘导航 - Android Keyboard Navigation in Jetpack Compose setTextIsSelectable如何防止键盘出现? - How does setTextIsSelectable prevent the keyboard from appearing? 如何防止软键盘出现触摸 - How to prevent soft keyboard from appearing on touch 如何防止 Jetpack Compose ExposedDropdownMenuBox 在滚动时显示菜单 - How to prevent Jetpack Compose ExposedDropdownMenuBox from showing menu when scrolling 使用 Jetpack Compose 构建软件键盘 - 使用 Jetpack Compose 的 IME 输入法 - Build Software Keyboard with Jetpack Compose - IME Input Method with Jetpack Compose
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM