androidandroid-jetpack-composeandroid-compose-textfield

Jetpack compose: Setting ImeAction does not close or change focus for the keyboard


I'm using Jetpack compose 1.0.0-alpha07. I made a login screen that contains two TextFields customized using other composables.

However, setting ImeAction in keyboardOptions does not seem to work. For instance ImeAction.Next does not move focus to the next TextField. I think I should do something to make it possible, but no document or article has talked even briefly about ImeOptions. Here's the code I have for the screen:

Login composable:

EmailEdit(onChange = { email.value = it })
PasswordEdit(onChange = { password.value = it })

EmailEdit:

@Composable
fun EmailEdit(onChange: (String) -> Unit) {
    val t = remember { mutableStateOf("") }
    TextField(
        value = t.value,
        onValueChange = { value ->
            t.value = value
            onChange(value)
        },
        leadingIcon = { Icon(asset = Icons.Default.Email) },
        label = { Text(text = "Email") },
        maxLines = 1,
        keyboardOptions = KeyboardOptions(
            imeAction = ImeAction.Next, // ** Go to next **
            keyboardType = KeyboardType.Email
        ),
        visualTransformation = VisualTransformation.None
    )
}      errorHint = "Not a valid email"
    )
}

PassEdit:

@Composable
fun PasswordEdit(onChange: (String) -> Unit) {
    val t = remember { mutableStateOf("") }
    TextField(
        value = t.value,
        onValueChange = { value ->
            t.value = value
            onChange(value)
        },
        leadingIcon = { Icon(asset = Icons.Default.Security) },
        label = { Text(text = "Password") },
        maxLines = 1,
        keyboardOptions = KeyboardOptions(
            imeAction = ImeAction.Done, // ** Done. Close the keyboard **
            keyboardType = KeyboardType.Text
        ),
        visualTransformation = PasswordVisualTransformation()
    )
}

To perform Done and Next what code should I add?


Solution

  • You can use

    For Done:

    You can use the LocalSoftwareKeyboardController to interact with the keyboard.

    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
    keyboardActions = KeyboardActions(
        onDone = {keyboardController?.hide()}
    )
    

    For Next:

    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
    keyboardActions = KeyboardActions(
        onNext = { focusRequester.requestFocus() }
    )
    

    Something like:

    val (focusRequester) = FocusRequester.createRefs()
    val keyboardController = LocalSoftwareKeyboardController.current
    
    TextField(
        value = text,
        onValueChange = {
            text = it
        },
        label = { Text("Label") },
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
        keyboardActions = KeyboardActions(
            onNext = { focusRequester.requestFocus() } 
        )
    )
    
    TextField(
        value = text,
        onValueChange = {
            text = it
        },
        modifier = Modifier.focusRequester(focusRequester),
        label = { Text("Label") },
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
        keyboardActions = KeyboardActions(
            onDone = { keyboardController?.hide() }
        )
    )