[英]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;
}
}
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.这不是一个真正干净的解决方案,而是一个很好的解决方法。
@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),
)
}
}
@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.