Android: Programmatically Show/Hide Soft keyboard

The Android soft keyboard has a special talent for appearing exactly when you don't want it and hiding exactly when you do. You tap a button after filling in a form — keyboard stays up. You navigate to a search screen — keyboard doesn't appear. You open a dialog — keyboard blocks the submit button.

Sound familiar? Controlling the keyboard programmatically is one of those deceptively simple tasks that comes with a surprising number of edge cases. This guide covers everything — showing, hiding, detecting visibility, Fragment support, the modern API for Android 11+, and every windowSoftInputMode value worth knowing.

Android soft keyboard show hide programmatically

Photo by Emojisprout on Unsplash

Quick Reference — Which API to Use?

Android Version Recommended API Notes
Android 11+ (API 30+) WindowInsetsController Modern, cleaner API
Android 10 and below InputMethodManager Legacy but still widely used

Hiding the Keyboard

In an Activity

import android.content.Context
import android.view.View
import android.view.inputmethod.InputMethodManager

fun Activity.hideKeyboard() {
    val view = currentFocus ?: View(this)
    val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.hideSoftInputFromWindow(view.windowToken, 0)
}

// Usage — call from anywhere in your Activity
hideKeyboard()

In a Fragment

fun Fragment.hideKeyboard() {
    val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE)
            as InputMethodManager
    val view = requireActivity().currentFocus ?: return
    imm.hideSoftInputFromWindow(view.windowToken, 0)
}

// Usage — call from anywhere in your Fragment
hideKeyboard()

From any View (utility function)

fun View.hideKeyboard() {
    val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE)
            as InputMethodManager
    imm.hideSoftInputFromWindow(windowToken, 0)
}

// Usage
binding.btnSubmit.setOnClickListener {
    it.hideKeyboard()
    // process form...
}

Showing the Keyboard

Show keyboard and focus an EditText

fun View.showKeyboard() {
    requestFocus()
    val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE)
            as InputMethodManager
    imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
}

// Usage — show keyboard when search screen opens
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    binding.etSearch.postDelayed({
        binding.etSearch.showKeyboard()
    }, 200) // Small delay needed for fragment transition to complete
}
💡 Why the postDelayed? If you call showSoftInput immediately in onViewCreated, the view may not be attached to the window yet and the keyboard won't appear. A small delay of 100–200ms ensures the view is ready.

Modern API — WindowInsetsController (Android 11+)

From Android 11 (API 30), Google introduced WindowInsetsController as the modern replacement for InputMethodManager. It's cleaner, more predictable, and part of the new insets API that handles everything from system bars to the keyboard:

import android.os.Build
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat

// Use WindowInsetsControllerCompat for backward compatibility
fun Activity.hideKeyboardModern() {
    val controller = WindowCompat.getInsetsController(window, window.decorView)
    controller.hide(WindowInsetsCompat.Type.ime())
}

fun Activity.showKeyboardModern() {
    val controller = WindowCompat.getInsetsController(window, window.decorView)
    controller.show(WindowInsetsCompat.Type.ime())
}

// In Fragment
fun Fragment.hideKeyboardModern() {
    val controller = WindowCompat.getInsetsController(
        requireActivity().window,
        requireView()
    )
    controller.hide(WindowInsetsCompat.Type.ime())
}
✅ Use WindowInsetsControllerCompat from AndroidX Core — it handles backward compatibility automatically and works on older API levels too. Add the dependency if you don't have it: implementation 'androidx.core:core-ktx:1.13.0'

Detecting Keyboard Visibility Changes

Sometimes you need to know when the keyboard appears or disappears — to adjust layout, scroll a list to the focused field, or animate a button. Here's how to listen for keyboard visibility changes using the modern insets API:

import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

// In Activity or Fragment
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, insets ->
    val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
    val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom

    if (imeVisible) {
        // Keyboard is showing — imeHeight is the keyboard height in pixels
        binding.btnSubmit.translationY = -imeHeight.toFloat()
    } else {
        // Keyboard is hidden
        binding.btnSubmit.translationY = 0f
    }

    insets
}

For this to work correctly, make sure your root view draws behind system bars:

// In Activity.onCreate() — before setContentView
WindowCompat.setDecorFitsSystemWindows(window, false)

windowSoftInputMode — All Values Explained

The windowSoftInputMode attribute in AndroidManifest.xml controls how the keyboard behaves when an Activity starts. It's split into two categories — initial state and resize behaviour — and you can combine one from each:

State values (keyboard visibility on launch)

Value Behaviour Use When
stateUnspecified System decides (default) Most cases
stateUnchanged Keep keyboard state from previous screen Multi-step forms
stateHidden Hide keyboard when Activity starts Screens with EditText not immediately needed
stateAlwaysHidden Always hide keyboard on start, even if user navigated back Home/landing screens
stateVisible Show keyboard when Activity starts Search screens, chat input
stateAlwaysVisible Always show keyboard on start Dedicated search/input screens

Resize values (how layout adjusts when keyboard appears)

Value Behaviour Use When
adjustUnspecified System decides (default) Most cases
adjustResize Resizes the Activity window to make room for keyboard Chat screens, comment boxes
adjustPan Pans the window up to keep focused view visible Fixed-height layouts, login screens
adjustNothing Layout doesn't adjust at all Full-screen apps managing insets manually

Combining values in AndroidManifest.xml

<!-- Hide keyboard on start, resize layout when it appears -->
<activity
    android:name=".MainActivity"
    android:windowSoftInputMode="stateHidden|adjustResize"/>

<!-- Show keyboard immediately, pan layout up -->
<activity
    android:name=".SearchActivity"
    android:windowSoftInputMode="stateVisible|adjustPan"/>

Common Use Cases

Hide keyboard when tapping outside an EditText

// In your Activity — override dispatchTouchEvent
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
    if (event.action == MotionEvent.ACTION_DOWN) {
        val view = currentFocus
        if (view is EditText) {
            val rect = Rect()
            view.getGlobalVisibleRect(rect)
            if (!rect.contains(event.rawX.toInt(), event.rawY.toInt())) {
                view.clearFocus()
                hideKeyboard()
            }
        }
    }
    return super.dispatchTouchEvent(event)
}

Hide keyboard when pressing Done/Enter on EditText

binding.etSearch.setOnEditorActionListener { _, actionId, _ ->
    if (actionId == EditorInfo.IME_ACTION_SEARCH ||
        actionId == EditorInfo.IME_ACTION_DONE) {
        hideKeyboard()
        performSearch(binding.etSearch.text.toString())
        true
    } else false
}

Show keyboard automatically on a search screen

class SearchFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Show keyboard as soon as search screen opens
        binding.etSearch.post {
            binding.etSearch.requestFocus()
            binding.etSearch.showKeyboard()
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        // Always clean up — hide keyboard when leaving the screen
        hideKeyboard()
    }
}

Best Practices

  • Always clean up in onDestroyView() — if you show the keyboard when a Fragment appears, hide it when it's destroyed. Leaving the keyboard open after navigation feels broken and jarring to users.
  • Use post() or postDelayed() when showing keyboard — calling showSoftInput before the view is attached to the window silently fails. Wrap it in view.post { ... } or add a short delay after fragment transitions.
  • Prefer WindowInsetsControllerCompat on new projects — it's the modern API, it's backward compatible via AndroidX, and it integrates with the edge-to-edge insets system that's now the default in Android 15+.
  • Use adjustResize for chat-style screens — when a keyboard appears in a chat UI, you want the message list to shrink and the input field to stay visible. adjustResize handles this automatically.
  • Don't use adjustPan with edge-to-edge — if your app uses WindowCompat.setDecorFitsSystemWindows(window, false) for edge-to-edge, adjustPan and adjustResize may not work as expected. Handle insets manually using ViewCompat.setOnApplyWindowInsetsListener instead.

Frequently Asked Questions

Why is hideSoftInputFromWindow not working?
The most common reason is passing a null or incorrect view token. Make sure you're using activity.currentFocus?.windowToken. If no view has focus, the keyboard won't hide. Also ensure you're calling it on the main thread.

How do I show the keyboard automatically when a Fragment opens?
Call requestFocus() and showSoftInput() inside view.post { } or with a short postDelayed of 100–200ms in onViewCreated(). The delay ensures the view is fully attached to the window before the keyboard appears.

What is the difference between adjustResize and adjustPan?
adjustResize shrinks the Activity's visible area to make room for the keyboard — the layout reflows. adjustPan scrolls the layout upward to keep the focused view visible without resizing. Use adjustResize for chat or form screens, adjustPan for fixed layouts.

How do I hide the keyboard when the user taps outside an EditText?
Override dispatchTouchEvent in your Activity. On ACTION_DOWN, check if the touch coordinates fall outside the currently focused EditText's bounds using getGlobalVisibleRect(). If they do, call clearFocus() and hideKeyboard().

📚 Continue Learning
📝 Summary
  • Use InputMethodManager for Android 10 and below
  • Use WindowInsetsControllerCompat for Android 11+ — cleaner and future-proof
  • Always wrap showSoftInput in view.post { } to avoid silent failures
  • Always hide keyboard in onDestroyView() if you showed it in onViewCreated()
  • Use adjustResize for chat/form screens, adjustPan for fixed layouts
  • Use ViewCompat.setOnApplyWindowInsetsListener to detect keyboard height changes
  • Don't mix adjustPan/adjustResize with edge-to-edge — handle insets manually instead

Pragnesh Ghoda

A forward-thinking developer offering more than 8 years of experience building, integrating, and supporting android applications for mobile and tablet devices on the Android platform. Talks about #kotlin and #android

Post a Comment

Please let us know about any concerns or query.

Previous Post Next Post

Contact Form