Jetpack Compose,文本字段中的自定义光标位置

Nic*_*nze 14 android kotlin android-jetpack-compose

当文本字段获得焦点时,如何将光标设置在其随机位置?相当于editText.setSelection(position)经典的 android 视图系统。

这是我用来让编辑文本在添加到屏幕时自动接收焦点的代码。我希望能够将光标从默认位置 0 移开

val (getText, setText) = remember { mutableStateOf("hello") }
AutofocusEditText(
    text = getText,
    setText = setText
)
    
...

@Composable
private fun AutofocusEditText(
    text: String,
    setText : (String) -> Unit
) {
    val focusState = remember { mutableStateOf(FocusState.Inactive) }
    val focusRequester = FocusRequester()
    val focusModifier = Modifier.focus()
    Row(
        modifier = Modifier.focusObserver { newFocusValue -> focusState.value = newFocusValue }
    ) {
        val focusRequesterModifier =
            Modifier.focusRequester(focusRequester)

        TextField(
            value = text,
            modifier = focusModifier.then(focusRequesterModifier),
            backgroundColor = Color.Transparent,
            onValueChange = setText,
            keyboardOptions = KeyboardOptions.Default.copy(
                imeAction = ImeAction.Done
            ),
            onImeActionPerformed = { action, softKeyboardController ->
                if (action == ImeAction.Done) {
                    softKeyboardController?.hideSoftwareKeyboard()
                }
            }
        )
    }
    onActive {
        focusRequester.requestFocus()
    }
}
Run Code Online (Sandbox Code Playgroud)

2ja*_*222 19

您必须使用 TextField 的 TextFieldValue 版本。

@Composable
fun TextField(
    value: TextFieldValue,
    onValueChange: (TextFieldValue) -> Unit,
    /* ... */) {/* Impl */}
Run Code Online (Sandbox Code Playgroud)

代码示例:编辑:Compose 版本 1.1.1 (13.04.22)

enum class CursorSelectionBehaviour {
    START, END, SELECT_ALL
}

@Composable
fun AutofocusTextFieldExample(
    initValue: String,
    behaviour: CursorSelectionBehaviour = CursorSelectionBehaviour.END
) {
    val direction = LocalLayoutDirection.current
    var tfv by remember {
        val selection = when (behaviour) {
            CursorSelectionBehaviour.START -> {
                if (direction == Ltr) TextRange.Zero else TextRange(initValue.length)
            }
            CursorSelectionBehaviour.END -> {
                if (direction == Ltr) TextRange(initValue.length) else TextRange.Zero
            }
            CursorSelectionBehaviour.SELECT_ALL -> TextRange(0, initValue.length)
        }
        val textFieldValue = TextFieldValue(text = initValue, selection = selection)
        mutableStateOf(textFieldValue)
    }
    val focusRequester = remember { FocusRequester.Default }
    TextField(
        modifier = Modifier.focusRequester(focusRequester),
        value = tfv,
        onValueChange = { tfv = it }
    )
    LaunchedEffect(Unit) {
        focusRequester.requestFocus()
    }
}
Run Code Online (Sandbox Code Playgroud)

旧版 (04.01.21):

    @Composable
    fun AutoFocusingText() {
        val textState = remember { mutableStateOf(TextFieldValue()) }
        val focusState = remember { mutableStateOf(FocusState.Inactive) }
        val focusRequester = FocusRequester()
        val focusModifier = Modifier.focus()
        Row(
            modifier = Modifier.focusObserver { focusState.value = it }
        ) {
            val focusRequesterModifier = Modifier.focusRequester(focusRequester)
            TextField(
                modifier = focusModifier.then(focusRequesterModifier),
                value = textState.value,
                onValueChange = { value: TextFieldValue ->
                    textState.value = value
                }
            )
        }
        onActive {
            focusRequester.requestFocus()
        }
    }
Run Code Online (Sandbox Code Playgroud)

如果您有一个非空字符串作为初始值,则必须手动更改选择。将空 TextFieldValue 替换为:TextFieldValue(text = value, selection = TextRange(value.length, value.length))

当您想要提取代码中的值时。您可以将当前选择添加为参数,也可以将其与 TextFieldValue 一起提取。否则,如果用户在文本中间进行编辑,则光标会在下一个 onValueChanged 时跳回到末尾。

  • 做这么简单的事情要承受如此巨大的痛苦。在我看来,末尾的光标应该是**默认**行为。至少,“TextField”应该有一个可选的构造函数参数“autoFocus: AutoFocus = AutoFocus.Start”,这样开发人员就不会被迫编写自己的解决方案。 (46认同)