By Zeeshan Mirza


2013-05-28 09:50:00 8 Comments

Is there any way in Android to get the height of the virtual keyboard displayed on the device in run time? Actually I want to show a text box above the keyboard.

10 comments

@Pierre 2019-10-08 05:45:56

This method works with adjustNothing or any windowSoftInputMode on your activity.

<activity android:name=".MainActivity"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:theme="@style/AppTheme"
        android:windowSoftInputMode="stateHidden|adjustNothing"/>

Using a PopupWindow, you can have separate "keyboard behaviour" for it, and it will notify you what the size of the keyboard is. The PopupWindow has the height of the screen, but 0px width, so you won't see it, it won't affect your activity, but will provide you with the information you need.

Create a class called KeyboardHeightProvider and add the following code:

public class KeyboardHeightProvider extends PopupWindow {
    public KeyboardHeightProvider(Context context, WindowManager windowManager, View parentView, KeyboardHeightListener listener) {
        super(context);

        LinearLayout popupView = new LinearLayout(context);
        popupView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        popupView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
            DisplayMetrics metrics = new DisplayMetrics();
            windowManager.getDefaultDisplay().getMetrics(metrics);

            Rect rect = new Rect();
            popupView.getWindowVisibleDisplayFrame(rect);

            int keyboardHeight = metrics.heightPixels - (rect.bottom - rect.top);
            int resourceID = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
            if (resourceID > 0) {
                keyboardHeight -= context.getResources().getDimensionPixelSize(resourceID);
            }
            if (keyboardHeight < 100) {
                keyboardHeight = 0;
            }
            boolean isLandscape = metrics.widthPixels > metrics.heightPixels;
            boolean keyboardOpen = keyboardHeight > 0;
            if (listener != null) {
                listener.onKeyboardHeightChanged(keyboardHeight, keyboardOpen, isLandscape);
            }
        });

        setContentView(popupView);

        setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
        setWidth(0);
        setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
        setBackgroundDrawable(new ColorDrawable(0));

        parentView.post(() -> showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0));
    }

    public interface KeyboardHeightListener {
        void onKeyboardHeightChanged(int keyboardHeight, boolean keyboardOpen, boolean isLandscape);
    }
}

Notice how the PopupWindow has its own setSoftInputMode(...), so it doesn't matter what you set your activity to, the PopupWindow will still be affected by the keyboard opening or closing and will provide the parent activity of the height. If the height is >= 100 you can assume the keyboard is open.

To use it, simply instantiate it in your Activity's onCreate(...) method after setContentView(...):

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    LinearLayout llRoot = findViewById(R.id.llRoot); //The root layout (Linear, Relative, Contraint, etc...)

    new KeyboardHeightProvider(this, getWindowManager(), llRoot, new KeyboardHeightProvider.KeyboardHeightListener() {
        @Override
        public void onKeyboardHeightChanged(int keyboardHeight, boolean keyboardOpen, boolean isLandscape) {
            Log.i("keyboard listener", "keyboardHeight: " + keyboardHeight + " keyboardOpen: " + keyboardOpen + " isLandscape: " + isLandscape);

            //Do what you want or have to with the parameters..
        }
    });

    //...
}

@Cristian Holdunu 2019-01-12 17:32:08

I've created a library project get android keyboard height, even when activities don't use the adjustResize input mode.

https://github.com/Crysis21/KeyboardHeightProvider

@Sagar Gadani 2018-03-09 09:00:03

I have used this to get keyboard height programmatically in android and tested it, please try this once:

myLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

                @Override
                public void onGlobalLayout() {
                    // TODO Auto-generated method stub
                    Rect r = new Rect();
                    parent.getWindowVisibleDisplayFrame(r);

                    int screenHeight = parent.getRootView().getHeight();
                    int heightDifference = screenHeight - (r.bottom - r.top);
                    Log.d("Keyboard Size", "Size: " + heightDifference);

                    //boolean visible = heightDiff > screenHeight / 3;
                }
            });

Thank you.

@Adib Faramarzi 2018-03-11 14:29:21

Do not forget removing the OnGlobalLayoutListener inside the callback.

@htafoya 2019-02-27 19:32:11

I use the same approach, but still some devices seem to have issue. One galaxy s9 with custom keyboard seem to be failing on this.

@Barakuda 2017-09-18 22:37:49

Look no more! I've been looking for a solution for this for a long time. After days of trying all the tricks suggested on SOF, I found the perfect solution that actually works.

This GitHub project demonstrates it the best way possible: https://github.com/siebeprojects/samples-keyboardheight

Have fun!

@Siebe Brouwer 2016-12-08 09:27:43

To solve this I have written a keyboardHeightProvider which can calculate the height of a floating soft keyboard. The Activity can be set to adjustNone or adjustPan in the AndroidManifest.xml.

https://github.com/siebeprojects/samples-keyboardheight

Siebe

@NehaK 2017-02-17 07:31:14

This is the best solution..

@Kishore Jethava 2017-04-03 09:52:08

10+ perfect bro!

@Vijay 2017-07-01 13:23:02

Is there any gradle dependency or jar available in this project?

@Sough 2017-08-25 15:56:30

the ONLY working solution for adjustNOTHING!

@Siebe Brouwer 2017-09-01 05:42:30

Am glad I could help with it. Cool to hear it works well.

@Maksim Ostrovidov 2017-09-10 06:41:53

Thanks for the solution. It would be great if you make lib out of it.

@Sniper 2018-09-30 15:56:27

This code doesnt work on phone with notch i am getting the wrong height...

@0101100101 2018-10-22 23:42:02

I thought this was working fine for so long, but then I noticed the height is wrong on Chromebooks in tablet mode :'(

@Fantasy Fang 2019-01-09 02:01:57

Great work! It can use in that the windowSoftInputMode is adjustNothing.

@Marc Alexander 2019-04-26 21:03:49

This is a life saver.

@neevek 2019-04-28 06:51:59

@Sniper, for phone with notch, you can try this.

@mco 2019-09-12 02:22:03

@vijay super late but, I dont think there is, you just have to see how it's used in the MainActivity of the project and copy the correct classes

@Gem 2014-05-06 06:54:09

My solution is the combination of all above solutions. This solution is also hacky but solve the problem (atleast for me).

  1. I have places on temporary view with transparent background at the bottom of the screen.
  2. I have added android:windowSoftInputMode="adjustResize" flag in activity tag in manifest like @bill suggests.
  3. Now main story is in onGlobalLayout(). There i calculate the difference between the y axis of temp view and height of root view

    final View view = findViewById(R.id.base);
    
    view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    
        @Override
        public void onGlobalLayout() {
    
            int rootViewHeight = view.getRootView().getHeight();
            View tv = findViewById(R.id.temp_view);
            int location[] = new int[2];
            tv.getLocationOnScreen(location);
            int height = (int) (location[1] + tv.getMeasuredHeight());
            deff = rootViewHeight - height;
            // deff is the height of soft keyboard
    
        }
    });
    

But anyways to solve the problem of @zeeshan0026 only a single flag in manifest android:windowSoftInputMode="adjustResize" is enough.

@VijayRaj 2014-12-05 06:47:37

Is it possible to get keyboard height by using android:windowSoftInputMode="adjustNothing" ?

@Gem 2014-12-17 05:56:19

If we use adjustNothing flag then the view will not render again when keyboard open so apparently onGlobalLayout should not call and we will not able to get the change in size. Though i did not try by myself but this is what expected.

@ctate 2016-01-29 01:18:31

You can't tell. No, really: you simply can't tell.

The keyboard does not need to be any particular shape. It does not have to be placed at the bottom of the screen (many of the most popular options are not), it does not have to keep its current size when you change text fields (almost none do depending on the flags). It does not even have to be rectangular. It may also just take over the entire screen.

(copy of my answer on a similar question, Getting the dimensions of the soft keyboard )

@Dave Lawrence 2015-01-22 19:07:49

I tried many suggested methods for this, but none seemed to work for Android SDL. I think this is either because the SDL display is "full screen" or that it sits within an "AbsoluteLayout" and therefore the height of the "View" never actually changes. This method worked for me:

Getting the dimensions of the soft keyboard

mRootWindow = getWindow();
mRootView = mRootWindow.getDecorView().findViewById(android.R.id.content);
mRootView.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
    public void onGlobalLayout(){
        Rect r = new Rect();
        View view = mRootWindow.getDecorView();
        view.getWindowVisibleDisplayFrame(r);
        // r.left, r.top, r.right, r.bottom
    }
    });

@Alexey Yakovenko 2015-02-11 21:15:19

Thanks for this answer, exactly what I needed. This works for calculating on-screen keyboard size without the adjustResize (which I don't want).

@Ari 2015-11-27 11:42:19

This is an excellent answer. @Dave Lawrence you should mention in the answer that it the Rect's height doesn't take into account the status bar.

@Sharm 2017-02-26 20:45:36

Doesn't work with "adjustNothing"

@drakeet 2017-05-22 09:51:35

Great! This works for adjustPan.

@Ali 2017-09-06 05:40:59

How to calculate the height of keyboard from this method?

@rupps 2017-09-24 01:21:39

oh my god! what a hidden gem I've found :)

@Usman Rana 2018-12-12 13:42:07

In my case : int heightDiff = mRootView.getHeight() - r.bottom; worked fine

@Techfist 2013-05-28 10:06:46

Yes you can, with the help of Viewtree Observer and global layout listener, just try below mentioned steps

  1. Get the root view of your layout
  2. get the Viewtree observer for this root, and add a global layout listener on top of this.

now whenever soft keyboard is displayed android will re-size your screen and you will receive call on your listener. That's it only thing you now need to do is calculate difference between height which your root view has after re-size and original size. If difference is more then 150 consider this as a keyboard has been inflated.

Below is a sample code

root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){
     public void onGlobalLayout(){
           int heightDiff = root.getRootView().getHeight()- root.getHeight();
           // IF height diff is more then 150, consider keyboard as visible.  
        }
  });

Regards, Techfist

@Jacky 2013-08-28 04:31:04

i think this only works when android:windowSoftInputMode="adjustResize"

@what is sleep 2013-12-06 19:50:04

this just gets whether or not the keyboard is shown, but it doesn't give you the height of the keyboard.

@Techfist 2013-12-09 07:04:05

Heightdiff will give you, the amount of space keyboard is taken up.

@Ali Shah Ahmed 2013-12-16 10:33:52

Is this height in pixels or dp?

@Techfist 2013-12-16 10:35:27

its in pixel...

@Thomas Keller 2014-12-01 11:36:13

150px is not enough for xxhdpi devices like the Nexus 5. Its better to convert this absolute pixel value from a dp value and use that instead. I use 120dp and that works well for Nexus 7 (xhdpi) and Nexus 5 (xxhdpi). Your experiences may vary, though...

@zionpi 2016-05-26 02:27:01

And android:windowSoftInputMode="adjustResize" should be put in the AndroidMainfest's Activity attribution where your soft keyboard has been used.

@NehaK 2017-02-17 06:32:29

But if we require "adjustNothing" then this code can't be useful....

@htafoya 2019-02-27 19:22:55

Doesn't work if activity is fullscreen

@Thiện Kopites 2019-09-06 05:01:34

Doesn't work, some devices this code still > 0 when keyboard is not opened int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight();

@null pointer 2013-05-28 09:55:17

put the text box as parent bottom.

android:layout_alignParentBottom="true"

and in the manifest file make the soft input adjustresize

android:windowSoftInputMode="adjustResize"

then the text box will move up when the keyboard appears.

@Lo-Tan 2015-05-17 20:38:38

I have a video view that is full screen that I do NOT want to move when the layout resizes, but I still want the text box to move and stay above the keyboard. How would one accomplish that?

@pesho 2016-02-04 09:19:57

@Lo-Tan this is exactly what I want to achieve as well. Did you figure out how to do it?

Related Questions

Sponsored Content

25 Answered Questions

[SOLVED] Is there a way to run Python on Android?

97 Answered Questions

26 Answered Questions

38 Answered Questions

[SOLVED] How to show soft-keyboard when edittext is focused

48 Answered Questions

[SOLVED] How do I "select Android SDK" in Android Studio?

47 Answered Questions

[SOLVED] Is there a unique Android device ID?

48 Answered Questions

[SOLVED] You need to use a Theme.AppCompat theme (or descendant) with this activity

19 Answered Questions

[SOLVED] Static way to get 'Context' in Android?

30 Answered Questions

[SOLVED] How do I obtain crash-data from my Android application?

8 Answered Questions

[SOLVED] Android error: Failed to install *.apk on device *: timeout

Sponsored Content