
Table of Contents
When building Android apps with Jetpack Compose, one of the first problems developers run into is how to hide the software keyboard at the right time. If the keyboard stays open after the user finishes typing, it can block important UI elements, overlap buttons, and create a clunky user experience.
If you have been working with the classic XML and EditText world, you might remember handling the keyboard with InputMethodManager. In Jetpack Compose, things are a bit different but also much cleaner once you know the right APIs.
In this article, weโll cover:
- Why controlling the keyboard is important
- The main APIs for hiding the keyboard in Compose
- Step-by-step code examples
- Handling keyboard dismissal in different scenarios
- Best practices and common pitfalls
Why Do You Need to Hide the Keyboard in Jetpack Compose?
The keyboard in Android usually opens automatically when a text field receives focus. Thatโs great for usability, but developers need to dismiss it when:
- The user presses a Submit or Done button
- The user navigates to a new screen where typing is not needed
- The user taps outside of the input field
- You want to clear focus programmatically after data entry
- You need to ensure a button or form at the bottom of the screen is not hidden behind the keyboard
Not handling the keyboard properly often leads to bad reviews because users find it frustrating when UI elements are blocked.
Methods to Hide the Keyboard in Jetpack Compose
There are three main approaches:
- Using
LocalSoftwareKeyboardController - Clearing focus with
LocalFocusManager - Dismissing keyboard on outside taps or navigation events
1. Hiding Keyboard with LocalSoftwareKeyboardController
@Composable
fun HideKeyboardWithController() {
var text by remember { mutableStateOf(TextFieldValue("")) }
val keyboardController = LocalSoftwareKeyboardController.current
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
OutlinedTextField(
value = text,
onValueChange = { text = it },
label = { Text("Type something") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { keyboardController?.hide() }, modifier = Modifier.fillMaxWidth()) {
Text("Submit")
}
}
}
This explicitly hides the keyboard when the Submit button is clicked.
2. Hiding Keyboard by Clearing Focus
@Composable
fun HideKeyboardByClearingFocus() {
var text by remember { mutableStateOf("") }
val focusManager = LocalFocusManager.current
OutlinedTextField(
value = text,
onValueChange = { text = it },
label = { Text("Enter text") },
modifier = Modifier.fillMaxWidth(),
keyboardActions = KeyboardActions(
onDone = { focusManager.clearFocus() }
)
)
}
Here, pressing Done on the keyboard automatically dismisses it.
3. Hiding Keyboard on Outside Tap
@Composable
fun HideKeyboardOnOutsideTap() {
var text by remember { mutableStateOf("") }
val focusManager = LocalFocusManager.current
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
.clickable { focusManager.clearFocus() }
.padding(16.dp)
) {
OutlinedTextField(
value = text,
onValueChange = { text = it },
label = { Text("Tap outside to hide keyboard") },
modifier = Modifier.fillMaxWidth()
)
}
}
This is useful when users expect the keyboard to close by tapping outside the input field.
Advanced: Hiding Keyboard on Navigation
@Composable
fun NavigationExample(navController: NavController = rememberNavController()) {
val focusManager = LocalFocusManager.current
Button(onClick = {
focusManager.clearFocus()
navController.navigate("nextScreen")
}) {
Text("Go to Next Screen")
}
}
Always clear focus before navigating so the keyboard doesnโt remain open on the next screen.
Common Pitfalls
- Relying only on
keyboardController.hide()โ it may not work consistently on all devices - Forgetting accessibility โ always provide clear submission actions
- Not testing on multiple devices โ OEM keyboards sometimes behave differently
Best Practices
- Prefer
focusManager.clearFocus()for reliability - Combine multiple approaches (Done button, outside taps, navigation)
- Always test on real devices and emulators
- Handle
KeyboardActionsfor better UX
Conclusion
Hiding the keyboard in Jetpack Compose is easier than it looks. Use LocalSoftwareKeyboardController for explicit control and LocalFocusManager for more natural dismissal through focus changes. By combining both approaches, your app will feel polished and professional, giving users a smoother experience.
FAQ
How do I hide the keyboard when pressing Done in Jetpack Compose?
Use KeyboardActions(onDone = { focusManager.clearFocus() }) inside your TextField.
How do I hide the keyboard when tapping outside a TextField?
Wrap your layout in a Modifier.clickable or Modifier.pointerInput and call focusManager.clearFocus().
Should I use InputMethodManager in Jetpack Compose?
No, Compose provides its own APIs. Use LocalSoftwareKeyboardController or LocalFocusManager instead.
Is LocalSoftwareKeyboardController reliable?
Yes, but for the best results combine it with focusManager.clearFocus() to cover all cases.
Do I need Kotlin to use these APIs?
Yes. Jetpack Compose is built for Kotlin, so these APIs are only available in Kotlin.



