Jetpack Compose,TextField 中的自定义光标位置

Jetpack Compose, custom cursor position in TextField

当 TextField 获得焦点时,如何将光标设置在它的随机位置? 相当于 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()
    }
}

您必须使用 TextField 的 TextFieldValue 版本。

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

代码示例: 编辑:撰写版本 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()
    }
}

旧 (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()
        }
    }

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

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