I need my calculator BasicTextField to show the cursor but not the keyboard. Currently, when I tap the BasicTextField for the first time, the cursor appears, but the keyboard does not. When I tap it a second time, the keyboard appears
Previously, I used CompositionLocalProvider(LocalTextInputService provides null), but it's now deprecated.
This is how my current code looks like:
BoxWithConstraints(
modifier = modifier
.fillMaxSize()
.padding(16.dp)
) {
val containerSize = minOf(maxWidth, maxHeight)
val fontSize = containerSize * 0.25f
val spacing = containerSize * 0.01f
val allowedCharacters = "0123456789+-×÷−%.,"
val keyboardController = LocalSoftwareKeyboardController.current
val focusRequester = remember { FocusRequester() }
val interactionSource = remember { MutableInteractionSource() }
LaunchedEffect(interactionSource) {
interactionSource.interactions.collect { interaction ->
if (interaction is PressInteraction.Release) {
focusRequester.requestFocus()
}
}
}
DisposableEffect(Unit) {
focusRequester.requestFocus()
keyboardController?.hide()
onDispose { }
}
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Bottom
) {
BasicTextField(
value = viewModel.currentExpression.value,
onValueChange = { newValue ->
// Filter the input to allow only the specified characters
val filteredValue = newValue.filter { it in allowedCharacters }
viewModel.currentExpression.value = filteredValue
},
singleLine = true,
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp, horizontal = 16.dp)
.focusRequester(focusRequester)
.onPreviewKeyEvent { keyEvent ->
if (keyEvent.type == KeyEventType.KeyDown &&
(keyEvent.key == Key.Enter || keyEvent.key == Key.NumPadEnter)) {
keyboardController?.hide()
true
} else {
false
}
},
maxLines = 1,
textStyle = TextStyle(
fontSize = fontSize.value.sp,
textAlign = TextAlign.End,
color = MaterialTheme.colorScheme.onSurface,
letterSpacing = spacing.value.sp
),
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.None,
keyboardType = KeyboardType.Number
),
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurface),
interactionSource = interactionSource
)
}
}
How can I ensure that the keyboard remains hidden while the cursor stays visible in the BasicTextField?
There is KeyboardOptions.showKeyboardOnFocus
property but it seems to be ignored by the current BasicTextField
implementations.
Try clearing the focus on each press and then refocusing on release while hiding the keyboard on a focus change:
BoxWithConstraints(
modifier = modifier
.fillMaxSize()
.padding(16.dp)
) {
val containerSize = minOf(maxWidth, maxHeight)
val fontSize = containerSize * 0.25f
val spacing = containerSize * 0.01f
val allowedCharacters = "0123456789+-×÷−%.,"
val keyboardController = LocalSoftwareKeyboardController.current
val focusManager = LocalFocusManager.current
val focusRequester = remember { FocusRequester() }
val interactionSource = remember { MutableInteractionSource() }
val isPressed by interactionSource.collectIsPressedAsState()
var refocus by rememberSaveable { mutableStateOf(false) }
LaunchedEffect(isPressed) {
if (isPressed) {
focusManager.clearFocus()
refocus = true
} else if (refocus) {
focusRequester.requestFocus()
refocus = false
}
}
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Bottom
) {
var text by remember { mutableStateOf("Text") }
BasicTextField(
value = viewModel.currentExpression.value,
onValueChange = { newValue ->
// Filter the input to allow only the specified characters
val filteredValue = newValue.filter { it in allowedCharacters }
viewModel.currentExpression.value = filteredValue
},
singleLine = true,
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp, horizontal = 16.dp)
.focusRequester(focusRequester)
.onFocusChanged {
keyboardController?.hide()
},
textStyle = TextStyle(
fontSize = fontSize.value.sp,
textAlign = TextAlign.End,
color = MaterialTheme.colorScheme.onSurface,
letterSpacing = spacing.value.sp
),
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.None,
keyboardType = KeyboardType.Number
),
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurface),
interactionSource = interactionSource
)
}
}