在 Jetpack Compose 中设置焦点顺序的最简单方法是什么?

Sea*_*ean 24 android android-jetpack-compose android-jetpack-compose-text

我有一列 TextFields,类似于:

Column {
    TextField(
        value = ...,
        onValueChange = { ... },
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.next),
    )
    TextField(
        value = ...,
        onValueChange = { ... },
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.next),
    )
    .
    .
    .
}
Run Code Online (Sandbox Code Playgroud)

我希望当用户按 Tab 或键盘上的下一个按钮时,每个 TextField 上的焦点移动到下一个。当前按 Tab 键会在 TextField 中插入一个选项卡。按下一步按钮不会执行任何操作。我可以为每个 TextField 创建一个 FocusRequester 并设置 KeyboardActions onNext 以请求将焦点放在每个 TextField 的下一个字段上。这有点乏味,而且它没有解决 Tab 行为。

Sea*_*ean 26

我最近发现这篇文章:https://medium.com/google-developer-experts/focus-in-jetpack-compose-6584252257fe

它解释了一种更简单的处理焦点的不同方法。

val focusManager = LocalFocusManager.current
TextField(
    modifier = Modifier
        .onPreviewKeyEvent {
            if (it.key == Key.Tab && it.nativeKeyEvent.action == ACTION_DOWN){
                focusManager.moveFocus(FocusDirection.Down)
                true
            } else {
                false
            }
        },
    value = text,
    onValueChange = { it -> text = it },
    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
    keyboardActions = KeyboardActions(
        onNext = { focusManager.moveFocus(FocusDirection.Down) }
    )
)
Run Code Online (Sandbox Code Playgroud)


ngl*_*ber 8

不确定这是否是更简单的方法,但您可以FocusRequester为每个字段创建一个对象,并按照您想要的顺序请求焦点。

@Composable
fun FocusRequestScreen() {
    // Create FocusRequesters... (you can use createRefs function)
    val focusRequesters = List(3) { FocusRequester() }

    Column {
        TextFieldWithFocusRequesters(focusRequesters[0], focusRequesters[1])
        TextFieldWithFocusRequesters(focusRequesters[1], focusRequesters[2])
        TextFieldWithFocusRequesters(focusRequesters[2], focusRequesters[0])
    }
}

@Composable
private fun TextFieldWithFocusRequesters(
    focusRequester: FocusRequester,
    nextFocusRequester: FocusRequester
) {
    var state by rememberSaveable {
        mutableStateOf("Focus Transition Test")
    }
    TextField(
        value = state,
        onValueChange = { text -> state = text },
        // Here it is what you want...
        modifier = Modifier
            .focusOrder(focusRequester) {
                nextFocusRequester.requestFocus()
            }
        ,
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next)
    )
}
Run Code Online (Sandbox Code Playgroud)

我从这里得到这个代码。但它并没有解决选项卡问题......:(

  • 不幸的是,如果焦点“TextField”被键盘覆盖,这个解决方案不会将屏幕向上移动......有什么线索可以实现这一点吗? (5认同)

Gar*_*ang 7

我目前正在compose_version = '1.0.2'.

当您按下下一个按钮时,焦点不会移动,因为虽然默认的键盘操作是将焦点移动到下一个,但 compose 似乎不知道下一个应该是哪一个。FocusRequester 为每个项目创建s 并通过设置其焦点顺序可以工作(顺便说一句,如果您选择这种方式,则Modifier.focusOrder() {}无需设置keyboardActionss来请求焦点),但由于您的s 位于相同的 s 中,因此您可以设置告诉 compose将焦点移至向下方向。就像是:onNextTextFieldColumnkeyboardActions

        Column {
            val focusManager = LocalFocusManager.current
            TextField(
                value = "", onValueChange = {},
                keyboardOptions = KeyboardOptions( imeAction = ImeAction.Next ),
                keyboardActions = KeyboardActions(
                    onNext = { focusManager.moveFocus(FocusDirection.Down) }
                )
            )
            TextField(
                value = "", onValueChange = {},
                keyboardOptions = KeyboardOptions( imeAction = ImeAction.Next ),
                keyboardActions = KeyboardActions(
                    onNext = { focusManager.moveFocus(FocusDirection.Down) }
                )
            )
            TextField(
                value = "", onValueChange = {},
                keyboardOptions = KeyboardOptions( imeAction = ImeAction.Next ),
                keyboardActions = KeyboardActions(
                    onNext = { focusManager.moveFocus(FocusDirection.Down) }
                )
            )
        }
Run Code Online (Sandbox Code Playgroud)

执行此操作后,IME 键盘上的下一个按钮应该可以使用。

对于Tab键,由于TextField不会自动处理Tab键,因此您可能需要使用focusManagerinsideModifier.onKeyEvent{}以与上面示例相同的方式移动焦点。


Gab*_*tti 5

关于订单你可以查看@nglauber的回答

要使用 Tab 键,您可以使用onKeyEvent修饰符

TextField(
    modifier = Modifier
        .focusRequester(focusRequester)
        .onKeyEvent {
            if (it.key.keyCode == Key.Tab.keyCode){
                focusRequesterNext.requestFocus()
                true //true -> consumed
            } else false },
    value = text,
    onValueChange = { it -> text = it },
    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
    keyboardActions = KeyboardActions(
        onNext = {focusRequesterNext.requestFocus()}
        )
)
Run Code Online (Sandbox Code Playgroud)