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

前端 未结 30 1358
情书的邮戳
情书的邮戳 2020-11-22 10:59

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

相关标签:
30条回答
  • 2020-11-22 11:44

    In my case i had only one EditText to manage in my layout so i came up whit this solution. It works well, basically it is a custom EditText which listens for focus and sends a local broadcast if the focus changes or if the back/done button is pressed. To work you need to place a dummy View in your layout with android:focusable="true" and android:focusableInTouchMode="true" because when you call clearFocus() the focus will be reassigned to the first focusable view. Example of dummy view:

    <View
    android:layout_width="1dp"
    android:layout_height="1dp"
    android:focusable="true"
    android:focusableInTouchMode="true"/>
    

    Additional infos

    The solution which detects the difference in layout changes doesn't work very well because it strongly depends on screen density, since 100px can be a lot in a certain device and nothing in some others you could get false positives. Also different vendors have different keyboards.

    0 讨论(0)
  • 2020-11-22 11:45

    I did this by setting a GlobalLayoutListener, as follows:

    final View activityRootView = findViewById(R.id.activityRoot);
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
            new OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    int heightView = activityRootView.getHeight();
                    int widthView = activityRootView.getWidth();
                    if (1.0 * widthView / heightView > 3) {
                        //Make changes for Keyboard not visible
                    } else {
                        //Make changes for keyboard visible
                    }
                }
            });
    
    0 讨论(0)
  • 2020-11-22 11:47

    You can refer to this answer - https://stackoverflow.com/a/24105062/3629912

    It worked for me everytime.

    adb shell dumpsys window InputMethod | grep "mHasSurface"
    

    It will return true, if software keyboard is visible.

    0 讨论(0)
  • 2020-11-22 11:49

    I had a similar problem. I needed to react to the Enter button on screen (which hid the keyboard). In this case you can subscribe to the OnEditorAction of the text view the keyboard was opend with - if you have multiple editable boxes, then subscribe to all of them.

    In your Activity you have full control of the keyboard, so at no point will you face the problem whether the keyboard is opened or not, if you listen to all opening and closing events.

    0 讨论(0)
  • 2020-11-22 11:52

    So after a long time of playing around with AccessibilityServices, window insets, screen height detection, etc, I think I found a way to do this.

    Disclaimer: it uses a hidden method in Android, meaning it might not be consistent. However, in my testing, it seems to work.

    The method is InputMethodManager#getInputMethodWindowVisibleHeight(), and it's existed since Lollipop (5.0).

    Calling that returns the height, in pixels, of the current keyboard. In theory, a keyboard shouldn't be 0 pixels tall, so I did a simple height check (in Kotlin):

    val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
    if (imm.inputMethodWindowVisibleHeight > 0) {
        //keyboard is shown
    else {
        //keyboard is hidden
    }
    

    I use Android Hidden API to avoid reflection when I call hidden methods (I do that a lot for the apps I develop, which are mostly hacky/tuner apps), but this should be possible with reflection as well:

    val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
    val windowHeightMethod = InputMethodManager::class.java.getMethod("getInputMethodWindowVisibleHeight")
    val height = windowHeightMethod.invoke(imm) as Int
    //use the height val in your logic
    
    0 讨论(0)
  • 2020-11-22 11:52

    I did this as follows, but its relevet only if your goal is to close / open the keyboad.

    close example: (checking if keyboard already closed, if not - closing)

    imm.showSoftInput(etSearch, InputMethodManager.HIDE_IMPLICIT_ONLY, new ResultReceiver(null) {
                        @Override
                        protected void onReceiveResult(int resultCode, Bundle resultData) {
                            super.onReceiveResult(resultCode, resultData);
                            if (resultCode != InputMethodManager.RESULT_UNCHANGED_HIDDEN)
                                imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                        }
                    });
    
    0 讨论(0)
提交回复
热议问题