如何使用箭头键将焦点从 Compose Button 移动到 Compose TextField?

How to move focus from Compose Button to Compose TextField by using the arrow key?

如何使用箭头键将焦点从“撰写”按钮移动到“撰写”TextField

当我使用箭头键(KeyEvent.KEYCODE_DPAD_UP),

将焦点从撰写按钮移动到撰写TextField

该键的焦点移动了两次。 (当我使用向上翻页键时)

我希望那个按键的焦点移动一次。

详情请看GIF动图

有办法解决这个问题吗?

(我使用向上键和向下键在 TextFields 之间移动 在onKeyEvent)

中使用focusManagermoveFocus方法
@Composable
fun Screen() {
    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        val focusManager = LocalFocusManager.current

        FocusMoveTextField(focusManager)
        FocusMoveTextField(focusManager)
        FocusMoveTextField(focusManager)

        OutlinedButton(
            onClick = {}
        ) {
            Text("Button")
        }
    }
}

@Composable
private fun FocusMoveTextField(
    focusManager: FocusManager
) {
    OutlinedTextField(
        modifier = Modifier
            .fillMaxWidth()
            .onKeyEvent { keyEvent ->
                when (keyEvent.nativeKeyEvent.keyCode) {
                    KEYCODE_DPAD_DOWN -> {
                        focusManager.moveFocus(FocusDirection.Down)
                        true
                    }
                    KEYCODE_DPAD_UP -> {
                        focusManager.moveFocus(FocusDirection.Up)
                        true
                    }
                    else -> {
                        false
                    }
                }
            },
        value = "",
        onValueChange = {},
        keyboardOptions = KeyboardOptions(
            keyboardType = KeyboardType.Number,
            imeAction = ImeAction.Done
        )
    )
}

测试后,我发现 onKeyEventButton 上按下一个键后会触发 2 次(ACTION_DOWN 1 次,ACTION_UP 1 次)。可能是按键时焦点移动两次
然后我认为你可以像

一样专注于你的 Button
val focusRequester = remember { FocusRequester() }
var buttonColor by remember { mutableStateOf(Black) }
OutlinedButton(
    onClick = { focusRequester.requestFocus() }, modifier = Modifier
        .focusRequester(focusRequester)
        .onFocusChanged { buttonColor = if (it.isFocused) Green else Black }
        .focusTarget()
        .onKeyEvent { keyEvent ->
            if (keyEvent.nativeKeyEvent.action == ACTION_UP) {
                when (keyEvent.nativeKeyEvent.keyCode) {
                    KEYCODE_DPAD_DOWN -> {
                        focusManager.moveFocus(FocusDirection.Down)
                        true
                    }
                    KEYCODE_DPAD_UP -> {
                        focusManager.moveFocus(FocusDirection.Up)
                        true
                    }
                    else -> {
                        false
                    }
                }
            } else {
                true
            }
        }
) {
    Text("Button", color = buttonColor)
}

完整示例

@Composable
fun Screen() {
    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        val focusManager = LocalFocusManager.current

        FocusMoveTextField(focusManager)
        FocusMoveTextField(focusManager)
        FocusMoveTextField(focusManager)

        val focusRequester = remember { FocusRequester() }
        var buttonColor by remember { mutableStateOf(Black) }
        OutlinedButton(
            onClick = { focusRequester.requestFocus() }, modifier = Modifier
                .focusRequester(focusRequester)
                .onFocusChanged { buttonColor = if (it.isFocused) Green else Black }
                .focusTarget()
                .onKeyEvent { keyEvent ->
                    if (keyEvent.nativeKeyEvent.action == ACTION_UP) {
                        when (keyEvent.nativeKeyEvent.keyCode) {
                            KEYCODE_DPAD_DOWN -> {
                                focusManager.moveFocus(FocusDirection.Down)
                                true
                            }
                            KEYCODE_DPAD_UP -> {
                                focusManager.moveFocus(FocusDirection.Up)
                                true
                            }
                            else -> {
                                false
                            }
                        }
                    } else {
                        true
                    }
                }
        ) {
            Text("Button", color = buttonColor)
        }
        FocusMoveTextField(focusManager)
        FocusMoveTextField(focusManager)
    }
}

@Composable
private fun FocusMoveTextField(
    focusManager: FocusManager
) {
    OutlinedTextField(
        modifier = Modifier
            .fillMaxWidth()
            .onKeyEvent { keyEvent ->
                when (keyEvent.nativeKeyEvent.keyCode) {
                    KEYCODE_DPAD_DOWN -> {
                        focusManager.moveFocus(FocusDirection.Down)
                        true
                    }
                    KEYCODE_DPAD_UP -> {
                        focusManager.moveFocus(FocusDirection.Up)
                        true
                    }
                    else -> {
                        false
                    }
                }
            },
        value = "",
        onValueChange = {},
        keyboardOptions = KeyboardOptions(
            keyboardType = KeyboardType.Number,
            imeAction = ImeAction.Done
        )
    )
}