DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Keyboard & IME in Compose: Soft Keyboard Control & Focus Management

Keyboard & IME in Compose: Soft Keyboard Control & Focus Management

Managing the soft keyboard and input focus in Jetpack Compose requires understanding imePadding, SoftwareKeyboardController, and FocusManager. This guide covers practical patterns for professional keyboard handling.

Handling IME Padding

The soft keyboard pushes content up automatically, but you can customize this behavior:

Column(
    modifier = Modifier
        .fillMaxSize()
        .imePadding()  // Adds padding when keyboard is visible
) {
    TextField(
        value = text,
        onValueChange = { text = it },
        modifier = Modifier.fillMaxWidth()
    )
}
Enter fullscreen mode Exit fullscreen mode

Use imePadding() alongside navigationBarsPadding() and statusBarsPadding() for proper inset handling:

Column(
    modifier = Modifier
        .fillMaxSize()
        .statusBarsPadding()
        .navigationBarsPadding()
        .imePadding()
) {
    // Your content
}
Enter fullscreen mode Exit fullscreen mode

Controlling Keyboard Visibility

val keyboardController = LocalSoftwareKeyboardController.current

Button(
    onClick = {
        keyboardController?.hide()
    }
) {
    Text("Hide Keyboard")
}
Enter fullscreen mode Exit fullscreen mode

Or show the keyboard on demand:

val focusRequester = remember { FocusRequester() }

LaunchedEffect(Unit) {
    focusRequester.requestFocus()
    keyboardController?.show()
}

TextField(
    value = text,
    onValueChange = { text = it },
    modifier = Modifier.focusRequester(focusRequester)
)
Enter fullscreen mode Exit fullscreen mode

KeyboardOptions & KeyboardType

TextField(
    value = email,
    onValueChange = { email = it },
    keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Email,
        imeAction = ImeAction.Done
    ),
    modifier = Modifier.fillMaxWidth()
)
Enter fullscreen mode Exit fullscreen mode

Common keyboard types:

  • KeyboardType.Email - Shows @ symbol
  • KeyboardType.Number - Numeric keypad
  • KeyboardType.Phone - Phone number layout
  • KeyboardType.Password - Hides input
  • KeyboardType.Decimal - Number with decimal point

Focus Management with KeyboardActions

val focusManager = LocalFocusManager.current
val focusRequester = remember { FocusRequester() }

Column {
    TextField(
        value = name,
        onValueChange = { name = it },
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
        keyboardActions = KeyboardActions(
            onNext = { focusRequester.requestFocus() }
        ),
        modifier = Modifier.fillMaxWidth()
    )

    TextField(
        value = email,
        onValueChange = { email = it },
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
        keyboardActions = KeyboardActions(
            onDone = { focusManager.clearFocus() }
        ),
        modifier = Modifier
            .fillMaxWidth()
            .focusRequester(focusRequester)
    )
}
Enter fullscreen mode Exit fullscreen mode

Programmatic Focus with FocusRequester

@Composable
fun LoginForm() {
    var email by remember { mutableStateOf("") }
    var password by remember { mutableStateOf("") }
    val focusRequester = remember { FocusRequester() }
    val focusManager = LocalFocusManager.current

    Column(modifier = Modifier.padding(16.dp)) {
        TextField(
            value = email,
            onValueChange = { email = it },
            label = { Text("Email") },
            keyboardOptions = KeyboardOptions(
                keyboardType = KeyboardType.Email,
                imeAction = ImeAction.Next
            ),
            keyboardActions = KeyboardActions(
                onNext = { focusRequester.requestFocus() }
            ),
            modifier = Modifier.fillMaxWidth()
        )

        TextField(
            value = password,
            onValueChange = { password = it },
            label = { Text("Password") },
            visualTransformation = PasswordVisualTransformation(),
            keyboardOptions = KeyboardOptions(
                keyboardType = KeyboardType.Password,
                imeAction = ImeAction.Done
            ),
            keyboardActions = KeyboardActions(
                onDone = { focusManager.clearFocus() }
            ),
            modifier = Modifier
                .fillMaxWidth()
                .focusRequester(focusRequester)
        )

        Button(onClick = { /* Login */ }, modifier = Modifier.align(Alignment.End)) {
            Text("Sign In")
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Best Practices

  1. Always use imePadding() to avoid content being hidden by the keyboard
  2. Chain focus with ImeAction.Next to create smooth multi-field forms
  3. Use ImeAction.Done on the last field to dismiss the keyboard
  4. Test on real devices - emulator keyboard behavior differs
  5. Combine KeyboardActions with FocusRequester for precise focus control

8 Android App Templates → https://myougatheax.gumroad.com

Top comments (0)