我正在使用 Jetpack Compose 中的 TextField 组件。 如何在它获得焦点时选择所有文本?
我正在使用 Jetpack Compose 中的 TextField 组件。 如何在它获得焦点时选择所有文本?
TextFieldValue
作为您的TextField
的状态,并且当它接收焦点时,您可以使用TextFieldValue
状态来设置selection
。val state = remember {
mutableStateOf(TextFieldValue(""))
}
TextField(
value = state.value,
onValueChange = { text -> state.value = text },
modifier = Modifier
.onFocusChanged { focusState ->
if (focusState.isFocused) {
val text = state.value.text
state.value = state.value.copy(
selection = TextRange(0, text.length)
)
}
}
)
这是结果:
请注意,根据您的触摸位置,光标会移动到触摸位置而不是选择整个文本。您可以尝试确定这是否是一个错误还是一项功能 :)
onValueChange
之前会调用onFocusChanged
。因此在onFocusChanged
期间发生的选择变更对于TextField
没有影响,因为它在onValueChange
期间被重写。var state by remember {
mutableStateOf(TextFieldValue("1231"))
}
var keepWholeSelection by remember { mutableStateOf(false) }
if (keepWholeSelection) {
// in case onValueChange was not called immediately after onFocusChanged
// the selection will be transferred correctly, so we don't need to redefine it anymore
SideEffect {
keepWholeSelection = false
}
}
TextField(
value = state,
onValueChange = { newState ->
if (keepWholeSelection) {
keepWholeSelection = false
state = newState.copy(
selection = TextRange(0, newState.text.length)
)
} else {
state = newState
}
},
modifier = Modifier
.onFocusChanged { focusState ->
if (focusState.isFocused) {
val text = state.text
state = state.copy(
selection = TextRange(0, text.length)
)
keepWholeSelection = true
}
}
)
我认为可以简化操作,因此在Compose问题跟踪器上创建了这个问题。
我写了一个修饰符扩展函数,尽管@Pylyp指出了一个错误,但它仍然有效。
fun Modifier.onFocusSelectAll(textFieldValueState: MutableState<TextFieldValue>): Modifier =
composed(
inspectorInfo = debugInspectorInfo {
name = "textFieldValueState"
properties["textFieldValueState"] = textFieldValueState
}
) {
var triggerEffect by remember {
mutableStateOf<Boolean?>(null)
}
if (triggerEffect != null) {
LaunchedEffect(triggerEffect) {
val tfv = textFieldValueState.value
textFieldValueState.value = tfv.copy(selection = TextRange(0, tfv.text.length))
}
}
Modifier.onFocusChanged { focusState ->
if (focusState.isFocused) {
triggerEffect = triggerEffect?.let { bool ->
!bool
} ?: true
}
}
}
使用方法
@Composable
fun SelectAllOnFocusDemo() {
var tfvState = remember {
mutableStateOf(TextFieldValue("initial text"))
}
TextField(
modifier = Modifier.onFocusSelectAll(tfvState),
value = tfvState.value,
onValueChange = { tfvState.value = it },
)
}
我对@nglauber的回答并没有100%的成功。你应该添加一个小延迟,这样就可以很好地工作了。例如:
val state = remember {
mutableStateOf(TextFieldValue(""))
}
// get coroutine scope from composable
val scope = rememberCoroutineScope()
TextField(
value = state.value,
onValueChange = { text -> state.value = text },
modifier = Modifier
.onFocusChanged {
if (it.hasFocus) {
// start coroutine
scope.launch {
// add your preferred delay
delay(10)
val text = state.value.text
state.value = state.value.copy(
selection = TextRange(0, text.length)
)
}
}
}
)
我想要补充一下Phil的回答,我想要动态更新状态,最终得到了这个:
var state by remember(textVal) {
mutableStateOf(TextFieldValue(text = textVal, selection = TextRange(textVal.length)))
}
它有两个作用,首先如果您的textVal
更改,则更新字段,同时将光标放在末尾。
imePadding
,我想知道是否会影响它的工作。我加入了100毫秒的延迟,问题得到了解决。 - Blake