Search code examples
androidkotlinandroid-jetpack-composeandroid-compose-dialog

JetpackCompose - "LocalFocusManager.current.moveFocus()" doesn't work in Dialog


I am trying to create a layout of a dialog with two TextFields. In doing so, I am trying to incorporate a feature that when the user completes the upper input field, it will be taken to the next input field by pressing the Next Key. However, it does not work.

In addition, I found out that it worked if not in Dialog.

Here is my code:

@Composable
fun TestDialog(
    openDialog: MutableState<Boolean>
) {
    val focusManager = LocalFocusManager.current
    val field1 = remember { mutableStateOf("") }
    val field2 = remember { mutableStateOf("") }

    Dialog(
        onDismissRequest = { openDialog.value = false }
    ) {
        Surface(
            shape = MaterialTheme.shapes.medium,
            color = MaterialTheme.colors.surface,
        ) {
            Box(
                modifier = Modifier.padding(
                    vertical = 16.dp,
                    horizontal = 16.dp
                ),
                contentAlignment = Alignment.Center
            ) {
                Column {
                    Text("Title")

                    Spacer(Spacer)

                    Text(
                        text = "message",
                        modifier = Modifier
                            .padding(bottom = 14.dp)
                            .alpha(ContentAlpha.medium),
                        style = MaterialTheme.typography.body2
                    )

                    OutlinedTextField(
                        modifier = Modifier.fillMaxWidth(),
                        value = field1.value,
                        onValueChange = { field1.value = it },
                        label = { Text("Label1") },
                        singleLine = true,
                        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
                        keyboardActions = KeyboardActions(
                            onNext = {
                                //it doesn't work.
                                focusManager.moveFocus(FocusDirection.Down)
                            }
                        )
                    )

                    Spacer(Spacer)
                    
                    OutlinedTextField(
                        modifier = Modifier
                            .fillMaxWidth()
                            .fillMaxHeight(0.8f),
                        value = field2.value,
                        onValueChange = { field2.value = it },
                        label = { Text("Label2") }
                    )

                    Row(
                        modifier = Modifier.align(Alignment.End),
                        horizontalArrangement = Arrangement.spacedBy(10.dp)
                    ) {

                        TextButton(onClick = { openDialog.value = false }) {
                            Text("CANCEL")
                        }

                        TextButton(onClick = {  }) {
                            Text("OK")
                        }

                    }

                }
            }
        }
    }
}

Solution

  • The Dialog has its own LocalFocusManager.

    You have to get its value inside the Dialog.

    Dialog(
      onDismissRequest = { false }
    ){
        //....
    
        val focusManager = LocalFocusManager.current
    
        OutlinedTextField(
            modifier = Modifier.fillMaxWidth(),
            value = field1.value,
            onValueChange = { field1.value = it },
            label = { Text("Label1") },
            singleLine = true,
            keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
            keyboardActions = KeyboardActions(
                onNext = {
                    focusManager.moveFocus(FocusDirection.Down)
                }
            )
        )
    }