更改光标位置并在Jetpack Compose中强制TextField的SingleLine [英] Change Cursor Position and force SingleLine of TextField in Jetpack Compose
问题描述
找不到改变TextField光标位置并使之成为单行的方法.有人找到一种方法吗?
Couldn't find a way to change the cursor position of TextField and making it singleline. Someone find a way to do it?
目前,我正在使用最新的jetpack-compose 1.0.0-alpha03
版本.
At this time, I'm using the latest jetpack-compose 1.0.0-alpha03
version.
推荐答案
要设置光标,您需要像这样设置TextFieldValue的选择:
To set the cursor you need to set the selection of the TextFieldValue like this:
@Composable
fun Content() {
val initTargetIndex = 3
val initValue = "string"
val initSelectionIndex = initTargetIndex.takeIf { it <= initValue.length } ?: initValue.length
val textFieldValueState = remember {
mutableStateOf(TextFieldValue(
text = initValue,
selection = TextRange(initSelectionIndex)
))
}
TextField(
modifier = Modifier.height(50.dp),
value = textFieldValueState.value,
onValueChange = { tfv -> textFieldValueState.value = tfv}
)
}
请记住,您需要自己从onValueChange更新选择,否则用户将无法移动光标或键入/删除.
Keep in mind you need to update the selection yourself from the onValueChange otherwise the user cannot move the cursor or type/delete.
对于单行,您需要在TextField Composable上设置一个固定的高度,并且可能要清除用户输入中的'\ n'.
To the single-line, you need to set a fixed height on the TextField Composable and you probably want to sanitize '\n' from the user input.
@Composable
fun Content() {
val initTargetIndex = 3
val initValue = "string"
val initSelectionIndex = initTargetIndex.takeIf { it <= initValue.length } ?: initValue.length
val textFieldValueState = remember {
mutableStateOf(TextFieldValue(
text = initValue,
selection = TextRange(initSelectionIndex)
))
}
TextField(
modifier = Modifier.height(50.dp),
value = textFieldValueState.value,
onValueChange = { tfv ->
val sanitizedText = tfv.text.replace("\n", "")
val needUpdate = sanitizedText.length >= tfv.text.length
if (needUpdate) {
textFieldValueState.value = tfv
}
},
)
}
对于后者,我对新文本进行消毒,并将其长度与状态文本进行比较,如果新文本较短,则无需更新状态,因为在消毒过程中我只是删除了字符. 如果只想阻止用户自己添加新行,则可以使高度不受限制.
For the latter, I sanitize the new text and compare the lengths of it and the state's text, if the new text is shorter I do not have to update the state because I just removed the character during sanitizing. If you just want to stop the user from adding new lines on their own, you can leave the height unconstrained.
以前的解决方案会忽略带有换行符的粘贴文本,如果要保留它,此onValueChange实现应正确处理它:
The previous solution ignores a pasted text with a line break, if you want to keep it this onValueChange implementation should handle it correctly:
val onValueChange = {tfv ->
textFieldValueState.value.let { old ->
val sanitizedText = tfv.text.replace("\n", "")
val lastPositionIndex = sanitizedText.length
val needUpdate = sanitizedText.length < tfv.text.length
val selection = if (needUpdate) {
tfv.selection.copy(
start = old.selection.start.takeUnless { it > lastPositionIndex} ?: lastPositionIndex,
end = old.selection.end.takeUnless { it > lastPositionIndex} ?: lastPositionIndex
)
} else tfv.selection
val composition = old.composition?.let { oldComp ->
if (needUpdate) {
TextRange(
start = oldComp.start.takeUnless { it > lastPositionIndex} ?: lastPositionIndex,
end = oldComp.end.takeUnless { it > lastPositionIndex} ?: lastPositionIndex
)
} else oldComp
}
textFieldValueState.value = tfv.copy(text = sanitizedText, selection = selection, composition = composition)
}
}
这篇关于更改光标位置并在Jetpack Compose中强制TextField的SingleLine的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!