How to check visibility of software keyboard in Android?

前端 未结 30 4492
半阙折子戏
半阙折子戏 2020-11-21 04:43

I need to do a very simple thing - find out if the software keyboard is shown. Is this possible in Android?

相关标签:
30条回答
  • 2020-11-21 05:33

    I have just encountered a bug while using most of the solutions above that suggest adding a fixed number.

    S4 is has a high dpi which resulted in the navigation bar's height being 100px thus my app thinking that the keyboard is open all the time.

    So with all the new high res phones being released i believe using a hard coded value is not a good idea for long term.

    A better approach that i found after some testing on various screens and devices was to use percentage. Get the difference between decorView and ur app content and afterwards check what is the percentage of that difference. From the stats that i got, most nav bar(regardless of the size, resolution etc..) will take between 3% to 5% of the screen. Where as if the keyboard is open it was taking between 47% to 55% of the screen.

    As a conclusion my solution was to check if the diff is more than 10% then i assume its a keyboard open.

    0 讨论(0)
  • 2020-11-21 05:35

    Instead of assuming the difference coding I did something like this, as I dint had menu options in my application.

    final View root= findViewById(R.id.myrootview); 
    root.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
        public void onGlobalLayout() {
            int heightDiff = root.getRootView().getHeight() - root.getHeight();
    
            Rect rectgle= new Rect();
            Window window= getWindow();
            window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
            int contentViewTop=                     
              window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
            if(heightDiff <= contentViewTop){
                //Soft KeyBoard Hidden
            }else{
                //Soft KeyBoard Shown
            }
         }
    });
    
    0 讨论(0)
  • 2020-11-21 05:35

    There is also solution with system insets, but it works only with API >= 21 (Android L). Say you have BottomNavigationView, which is child of LinearLayout and you need to hide it when keyboard is shown:

    > LinearLayout
      > ContentView
      > BottomNavigationView
    

    All you need to do is to extend LinearLayout in such way:

    public class KeyboardAwareLinearLayout extends LinearLayout {
        public KeyboardAwareLinearLayout(Context context) {
            super(context);
        }
    
        public KeyboardAwareLinearLayout(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
        public KeyboardAwareLinearLayout(Context context,
                                         @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        public KeyboardAwareLinearLayout(Context context, AttributeSet attrs,
                                         int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        @Override
        public WindowInsets onApplyWindowInsets(WindowInsets insets) {
            int childCount = getChildCount();
            for (int index = 0; index < childCount; index++) {
                View view = getChildAt(index);
                if (view instanceof BottomNavigationView) {
                    int bottom = insets.getSystemWindowInsetBottom();
                    if (bottom >= ViewUtils.dpToPx(200)) {
                        // keyboard is shown
                        view.setVisibility(GONE);
                    } else {
                        // keyboard is hidden
                        view.setVisibility(VISIBLE);
                    }
                }
            }
            return insets;
        }
    }
    

    The idea is that when keyboard is shown, system insets are changed with pretty big .bottom value.

    0 讨论(0)
  • 2020-11-21 05:35

    99% of solutions here are based on probability of IME WINDOW SIZE and each such solution is a sh... worth!

    because:

    1. OVERLAYS - from User apps or System apps
    2. IME have no MINIMUM SIZE it can take 100% of window size and can be so thin as imagination of developer implementation :)
    3. MODAL windows / MULTI windows
    4. and many many more like no knowledge of IPC (eg: foreign window or its content detection)

    so guessing it's IME is always wrong - don't guess be sure !!!

    @kevin-du is best solution wright now as its query IMM for IME height - but as it said the method is hidden API so using it could be dangerous in the way of getting wrong "false negative results" - by wrong dev usage.

    0 讨论(0)
  • 2020-11-21 05:35

    I know that this is a old post but I think this is the simplest approach that I know and my test device is Nexus 5. I haven't tried it in other devices. Hope that others will share their approach if they find my code is not good :)

    public static boolean isKeyboardShown(Context context, View view) {
            if (context == null || view == null) {
                return false;
            }
            InputMethodManager imm = (InputMethodManager) context
                    .getSystemService(Context.INPUT_METHOD_SERVICE);
            return imm.hideSoftInputFromWindow(view.getWindowToken(), 0); 
    }
    

    imm.hideSoftInputFromWindow returns boolean.

    Thanks,

    0 讨论(0)
  • 2020-11-21 05:36

    Try this:

    final View activityRootView = getWindow().getDecorView().getRootView();
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Rect r = new Rect();
            //r will be populated with the coordinates of your view that area still visible.
            activityRootView.getWindowVisibleDisplayFrame(r);
    
            int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
            if (heightDiff < activityRootView.getRootView().getHeight() / 4 ) { // if more than 100 pixels, its probably a keyboard...
                 // ... do something here ... \\
            }
        }
    });
    
    0 讨论(0)
提交回复
热议问题