How do I detect if software keyboard is visible on Android Device or not?

318,378

Solution 1

There is no direct way - see http://groups.google.com/group/android-platform/browse_thread/thread/1728f26f2334c060/5e4910f0d9eb898a where Dianne Hackborn from the Android team has replied. However, you can detect it indirectly by checking if the window size changed in #onMeasure. See How to check visibility of software keyboard in Android?.

Solution 2

This works for me. Maybe this is always the best way for all versions.

It would be effective to make a property of keyboard visibility and observe this changes delayed because the onGlobalLayout method calls many times. Also it is good to check the device rotation and windowSoftInputMode is not adjustNothing.

boolean isKeyboardShowing = false;
void onKeyboardVisibilityChanged(boolean opened) {
    print("keyboard " + opened);
}

// ContentView is the root view of the layout of this activity/fragment    
contentView.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {

        Rect r = new Rect();
        contentView.getWindowVisibleDisplayFrame(r);
        int screenHeight = contentView.getRootView().getHeight();

        // r.bottom is the position above soft keypad or device button.
        // if keypad is shown, the r.bottom is smaller than that before.
        int keypadHeight = screenHeight - r.bottom;

        Log.d(TAG, "keypadHeight = " + keypadHeight);

        if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
            // keyboard is opened
            if (!isKeyboardShowing) {
                isKeyboardShowing = true
                onKeyboardVisibilityChanged(true)
            }
        }
        else {
            // keyboard is closed
            if (isKeyboardShowing) {
                isKeyboardShowing = false
                onKeyboardVisibilityChanged(false)
            }
        }
    }
});

Solution 3

try this:

InputMethodManager imm = (InputMethodManager) getActivity()
            .getSystemService(Context.INPUT_METHOD_SERVICE);

    if (imm.isAcceptingText()) {
        writeToLog("Software Keyboard was shown");
    } else {
        writeToLog("Software Keyboard was not shown");
    }

Solution 4

I created a simple class that can be used for this: https://github.com/ravindu1024/android-keyboardlistener. Just copy it in to your project and use as follows:

KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
    @Override
    public void onToggleSoftKeyboard(boolean isVisible)
    {
        Log.d("keyboard", "keyboard visible: "+isVisible);
    }
});

Solution 5

Very Easy

1. Put id on your root view

rootView is just a view pointing to my root view in this case a relative layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/addresses_confirm_root_view"
                android:background="@color/WHITE_CLR">

2. Initialize your root view in your Activity:

RelativeLayout rootView = (RelativeLayout) findViewById(R.id.addresses_confirm_root_view);

3. Detect if keyboard is opened or closed by using getViewTreeObserver()

    rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightDiff = rootView.getRootView().getHeight() - rootView.getHeight();
                
                if (heightDiff > 100) { // Value should be less than keyboard's height 
                    Log.e("MyActivity", "keyboard opened");
                } else { 
                    Log.e("MyActivity", "keyboard closed");
                }
            }
        });
Share:
318,378

Related videos on Youtube

andreea
Author by

andreea

:)

Updated on February 10, 2022

Comments

  • andreea
    andreea about 2 years

    Is there a way in Android to detect if the software (a.k.a. "soft") keyboard is visible on screen?

    • Heath Hunnicutt
      Heath Hunnicutt about 12 years
    • Prof
      Prof over 6 years
      what can be a solution to this in certain cases (if a 3rd party keyboard is installed) is to check the global notifications as when a keyboard is open there is a system notification that says "change keyboard" - can be done with a NotificationListenerService
    • M.kazem Akhgary
      M.kazem Akhgary over 5 years
      almost 8 years and still no solid solution, oh if they introduce one, its going to be for API > 30 anyway so never mind...
    • AbdelHady
      AbdelHady over 4 years
      Possible duplicate of Android: Detect softkeyboard open
  • Peter Ajtai
    Peter Ajtai about 12 years
    This does not work for me. The keyboard shown branch triggers even in instance when the keyboard was never shown or was shown and then closed.
  • 3c71
    3c71 over 11 years
    Doesn't work for me. I only receive the Enter key in OnEditorAction.
  • Shivang Trivedi
    Shivang Trivedi over 10 years
    it always return true.
  • Léon Pelletier
    Léon Pelletier about 10 years
    Yeah, it always return true.
  • Gaurav Arora
    Gaurav Arora about 10 years
    Wrong. This always returns true
  • Denys Kniazhev-Support Ukraine
    Denys Kniazhev-Support Ukraine over 9 years
    This will be called VERY often
  • Gopal Singh Sirvi
    Gopal Singh Sirvi almost 9 years
    The question was related to find out either keyboard is showing or not
  • Boris Treukhov
    Boris Treukhov over 8 years
    For me it sometimes returns false - when the keyboard is actually visible.
  • Vicky Chijwani
    Vicky Chijwani over 8 years
    It is pathetic that the Android framework is lacking, and worse, inconsistent in this regard. This ought to be super-simple.
  • iscariot
    iscariot over 8 years
    not correctly working in some cases! Need something else
  • User3
    User3 over 8 years
    Can you improve this answer with a more concrete example, with all imports and a working example?
  • ToolmakerSteve
    ToolmakerSteve over 8 years
    This is only useful during development - not a solution for use in an app. (Users won't have adb running.)
  • Rarw
    Rarw about 8 years
    This works. If you implement as singelton you can apply to all edittexts on focus change and have one global keyboard listener
  • Christopher Hackl
    Christopher Hackl about 8 years
    @depperm getActivity() is specific to Fragments, try YourActivityName.this instead. See also: stackoverflow.com/questions/14480129/…
  • toom
    toom over 7 years
    Where in the code exaclty do I have to put this? I put this into an activity, however, it does not detect any keyboard appearance or disappearance.
  • ravindu1024
    ravindu1024 over 7 years
    Well, you can put it anywhere inside your activity. Just put it in the onCreate() method after the setContentView() call and you should be getting callbacks. Btw, what device are you trying it on?
  • Mahdi Astanei
    Mahdi Astanei over 7 years
    how to call it and where?
  • anthonymonori
    anthonymonori over 7 years
    This will only work for hardware keyboard, not he software one
  • Ganpat Kaliya
    Ganpat Kaliya over 7 years
    It is not working for me it returns always true. if the keyboard is not open still return true.
  • Evan Langlois
    Evan Langlois over 7 years
    In what instances will this be different than @BrownsooHan answer? I'm looking for a way that an app that draws over other apps to get out of the way of the keyboard is showing.
  • PearsonArtPhoto
    PearsonArtPhoto over 7 years
    His answer is fundamentally the same as mine, only I did mine many months before his, and he has more upvotes.
  • Faruk Toptas
    Faruk Toptas over 7 years
  • Justin
    Justin about 7 years
    Put this in a utils class and pass in the activity - now useful across the whole app.
  • narancs
    narancs almost 7 years
    hey mate, could you please tell me where this magic 100 comes from? Why not 101 or 99? Thanks
  • ravindu1024
    ravindu1024 almost 7 years
    @MaulikDodia I checked and it works fine in fragments. Set it up like this: KeyboardUtils.addKeyboardToggleListener(getActivity(), this); and it should work. What device are you trying it on?
  • Maulik Dodia
    Maulik Dodia almost 7 years
    I'm trying on Moto-G3 device.@ravindu1024
  • Code-Apprentice
    Code-Apprentice almost 7 years
    And where is contentView declared?
  • airowe
    airowe almost 7 years
    @Code-Apprentice In the activity/fragment you're looking to respond to soft keyboard changes. ContentView is the root view of the layout of this activity/fragment.
  • Rushi M Thakker
    Rushi M Thakker almost 7 years
    It always returns false in my case when I have a keyboard open and I select an item in custom autocompleteview
  • Vlad
    Vlad over 6 years
    @Karoly i think this may be and 1. No matter. Only this must be less than the real length of keyboard
  • mr5
    mr5 over 6 years
    @Karoly basically, he's comparing the window size with your activity's root view size. the appearance of the soft keyboard doesn't affect the size of the main window. so you can still lower the value of 100.
  • Vahe Gharibyan
    Vahe Gharibyan over 6 years
    No any way to detect is keyboard open or close. It's very embarrassing measure height for detecting keyboard state. I tried to find keyboard state inside of WindowManager because keyboard must attache some window.
  • V.March
    V.March almost 6 years
    Worked for me on Android 6 and 7.
  • Haresh Ramani
    Haresh Ramani almost 6 years
    this is perfect for me
  • Zeeshan
    Zeeshan over 5 years
    This logic is only for portrait mode. And onGlobalLayout() this method calls so many times, still looking for better solution.
  • Brownsoo Han
    Brownsoo Han over 5 years
    @ShanXeeshi Good point! It would be effective to make a property of keyboard visibility and observe this changes delayed because the onGlobalLayout method calls many times. Also check the device rotation.
  • Parth Patel
    Parth Patel over 5 years
    Working in lower and higher devices
  • 6rchid
    6rchid over 5 years
    This obviously won't work since it's not a listener that listens to the soft keyboard's behavior.
  • user924
    user924 about 5 years
    @VickyChijwani believe me Android SDK is much better than iOS SDK. It's much easier to develop for Android. To detect internet connection in iOS you have to use such things like github.com/ashleymills/Reachability.swift (in Android you need a couple of lines without any third-party code)
  • user924
    user924 about 5 years
    This bad because it always being called, even when I just scroll though items in RecyclerView
  • Brownsoo Han
    Brownsoo Han almost 5 years
    @vishalpatel If you use spited screen(fragment) with one activity, try to add listener to root of an activity.
  • Antroid
    Antroid almost 5 years
    not really a hack, didnt work in a nested fragment case. Can't say on activities as i didnt try this on that yet.
  • Antroid
    Antroid almost 5 years
    where would you remove Global layout listener. The number of times a global layout is called is unimagnable.
  • Brownsoo Han
    Brownsoo Han almost 5 years
    @antroid You need to create a property for checking keyboard visibility because GlobalLayoutListener called many many times. I updated codes.
  • Morten Holmgaard
    Morten Holmgaard over 4 years
    The magic number is dependent on your layout of topbar among other things. So it is relative to your app. I used 400 in one of mine.
  • Pratik Butani
    Pratik Butani over 4 years
    Thanks for this snippet, I have one question that is this code required to remove listener?
  • ravindu1024
    ravindu1024 over 4 years
    @PratikButaniAndroidDev There's a static function called KeyboardUtils.removeAllKeyboardToggleListeners. Call that when your Activity is destroyed.
  • Pratik Butani
    Pratik Butani over 4 years
    Is it required or not?
  • ravindu1024
    ravindu1024 over 4 years
    It isn't required for it to work. However since the keyboard util class is holding a static reference to your activity to provide that callback you should unregister to avoid memory leaks.
  • 9paradox
    9paradox over 4 years
    remember that onGlobalLayout is called every frame, so make sure you don't do heavy stuff in there.
  • Mandeep Singh
    Mandeep Singh over 4 years
    The isKeyboardShown keep on calling itself when its not shown.
  • Edgar Khimich
    Edgar Khimich over 4 years
    the fun onKeyboardVisibilityChanged() is actually can be removed Its better to put the code from there directly to the onGlobalLayoutListener The rest is work for me +1 Thanks
  • Syam Sundar K
    Syam Sundar K over 4 years
    this will not be helpful if your layout involves a bottom sheet. Can't distinguish between a keyboard and bottom sheet.
  • Amar Singh
    Amar Singh about 4 years
    working for me tested in 3 devices. motorola moto g5, micormax, nokia 6.1 plus
  • Foster
    Foster almost 4 years
    Works great. Thank you sm
  • kaustubhpatange
    kaustubhpatange almost 4 years
    Amazing use of reflections
  • Rafael
    Rafael almost 4 years
    They did hide this method
  • dokam_scotland
    dokam_scotland over 3 years
    easier solution ever for this situation ;)
  • Nurlan Nabiyev
    Nurlan Nabiyev over 3 years
    Спасибо! Ты спас мое время =)
  • Tom Gilder
    Tom Gilder over 3 years
    See this video which also references this question! youtube.com/watch?v=acC7SR1EXsI 😁
  • user158
    user158 over 3 years
    @TomGilder just go ahead and make an edit to add the video to references.
  • Andrew
    Andrew over 3 years
    And what is "binding"
  • Emre Akcan
    Emre Akcan over 3 years
    @Andrew it is root layout
  • Nishant Pardamwar
    Nishant Pardamwar over 3 years
    this actually breaks when user do split screen apps.
  • Pointer Null
    Pointer Null over 3 years
    Yes this works. Shame that we have to poll this, and some callback doesn't tell us when this changes.
  • Pravin Suthar
    Pravin Suthar about 3 years
    but this is not working in other third-party apps
  • Saman Sattari
    Saman Sattari about 3 years
    requires api 20 at least
  • AndrazP
    AndrazP almost 3 years
    I had to replace WindowInsetsCompat.toWindowInsetsCompat(rootWindowInsets) with ViewCompat.getRootWindowInsets(this) to get it working. Found it in Android video: youtu.be/acC7SR1EXsI?t=319
  • Aldan
    Aldan almost 3 years
    Works perfectly if you're using findViewById, if using View Binding we got error (act.findViewById<View>(… ViewGroup).getChildAt(0) must not be null any suggestion?
  • Hitesh Bisht
    Hitesh Bisht almost 3 years
    You can write an extension function like this for API 21 and above. fun View.isKeyboardVisible(): Boolean { val insets = ViewCompat.getRootWindowInsets(this) return insets?.isVisible(WindowInsetsCompat.Type.ime()) ?: false }
  • Inside 4ndroid
    Inside 4ndroid over 2 years
    your code should have getWindow().getDecorView() /** * Add global layout listener to observe system keyboard visibility */ private void initObserverForSystemKeyboardVisibility() { getWindow().getDecorView().getRootView().getViewTreeObserver‌​().addOnGlobalLayout‌​Listener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { //Add your own code here Log.d("TEST_CODE", "isSystemKeyboardVisible:" + isSystemKeyboardVisible()); } }); }
  • user924
    user924 over 2 years
    it has nothing to do with soft virtual keyboard
  • user924
    user924 over 2 years
    Thead.sleep - what is that? Making Main thread sleep?
  • user924
    user924 over 2 years
    Thead.sleep - what is that? Making Main thread sleep?
  • user924
    user924 over 2 years
    it returns 190, so it says that keyboard is always opened, this hardcoding is very bad
  • user924
    user924 over 2 years
    this returns true for Android 23-29 even if keyboard is not opened, it only works ok for Android 30
  • Gert Arnold
    Gert Arnold over 2 years
    You need a very good reason to answer an old, abundantly answered question like this. New answers without any explanation how they complement other answers tend to get deleted in the review process.
  • Piotr Aleksander Chmielowski
    Piotr Aleksander Chmielowski over 2 years
    @GertArnold If this -1 is from you, it would be more professional to at least explain what is wrong with the answer.
  • Gert Arnold
    Gert Arnold over 2 years
    Didn't I do that? For all answers an explanation why it does what it does (and it's the best way) is always welcome, but new answers to old questions should also explain how they improve other answers. You don't want to how many people just drop answers without ever looking at existing answers and, thus, effectively only add noise. Either way, code-only answers are always deemed low quality answers and many of them get deleted by community moderation.
  • RufusInZen
    RufusInZen over 2 years
    getInputMethodWindowVisibleHeight method is blocked as part of using non-SDK API lists. You cannot use this reflection in production. See more info here: developer.android.com/guide/app-compatibility/…
  • Ângelo Polotto
    Ângelo Polotto over 2 years
    so far, the only solution that still works in 2022!
  • Muhammad Maqsood
    Muhammad Maqsood about 2 years
    This workaround will work only when we have the below properties for activity in the Manifest file. android:windowSoftInputMode="adjustResize" or android:windowSoftInputMode="adjustPan" It will not work for below android:windowSoftInputMode="adjustNothing"