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

Time:01-13

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

When I have moved focus from Compose Button to Compose TextField by using the arrow key(KeyEvent.KEYCODE_DPAD_UP),

the focus moves twice for that key press. (when I use page-up-key)

I hope that the focus moves once for that key press.

Please see GIF animation for details

Is there a way to fix this?

(I use up-key and down-key in moving between TextFields using moveFocus method of focusManager in onKeyEvent)

@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
        )
    )
}

CodePudding user response:

After testing I see that onKeyEvent will fired 2 times after press a key on Button (1 for ACTION_DOWN and 1 for ACTION_UP). Maybe it cause the focus move twice when press a key.
Then I think you can handle focus on your Button like

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

Complete example

@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
        )
    )
}
  •  Tags:  
  • Related