Is there any way in Android to get the height of virtual keyboard of device

AndroidSdk

Android Problem Overview


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.

Android Solutions


Solution 1 - Android

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

Solution 2 - Android

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:

https://stackoverflow.com/questions/13534365/getting-the-dimensions-of-the-soft-keyboard

Window mRootWindow = getWindow();
View 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
	}
    });

Solution 3 - Android

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

Solution 4 - Android

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.

Solution 5 - Android

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..
        }
    });
    
    //...
}

Solution 6 - Android

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, https://stackoverflow.com/questions/13534365/getting-the-dimensions-of-the-soft-keyboard )

Solution 7 - Android

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

Solution 8 - Android

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.

Solution 9 - Android

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.

Solution 10 - Android

As the navigation bars, keyboard, etc are added to the window, you can measure these insets to check if the keyboard is open or not. With Android R, you can measure the keyboard directly, but you can fall back to calculating the keyboard size from the insets for prior versions.

This works on Lollipop and up.

getWindow().getDecorView()
               .setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
             
                   @Override
                   public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
                       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                           mKeyboardShowing =
                                   insets.getInsets(WindowInsets.Type.ime()).bottom > 0;
                           if (mKeyboardShowing) {
                               setKeyboardHeight(
                                       insets.getInsets(WindowInsets.Type.ime()).bottom -
                                       insets.getInsets(WindowInsets.Type.navigationBars()).bottom);
                           }
                       } else {
                           mKeyboardShowing = getNavigationBarHeight() !=
                                              insets.getSystemWindowInsetBottom();
                           if (mKeyboardShowing) {
                               setKeyboardHeight(insets.getSystemWindowInsetBottom() -
                                                 getNavigationBarHeight());
                           }
                       }
                       return v.onApplyWindowInsets(insets);
                   }

                   public int getNavigationBarHeight() {
                       boolean hasMenuKey = ViewConfiguration.get(MainActivity.this)
                                                             .hasPermanentMenuKey();
                       int resourceId = getResources().getIdentifier("navigation_bar_height",
                                                                     "dimen",
                                                                     "android");
                       if (resourceId > 0 && !hasMenuKey) {
                           return getResources().getDimensionPixelSize(resourceId);
                       }
                       return 0;
                   }
               });

Solution 11 - Android

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!

Solution 12 - Android

I finally found the solution to get the height of soft/virtual keyboard. I cannot say this works on all devices, but I tried on some devices both real and emulator devices and it works. I tried on devices from Android API 16 to 29. It is a little bit tricky. Here is my analysis.

First, I tried to subtract between the height of the screen and height of visible frame on top of soft/virtual keyboard by using function of getHeightDifference() such as below. I found that at the first time the layout is created, right before the keyboard open on EditText's focus, the difference height will depend on Android System Navigation Bar, either the Navigation Bar is shown inside the device screen or not. So, the value of heightDifference will be 0 if the Nav Bar outside the screen or greater than 0 if it is inside the screen. I'm using a variable of systemNavigationBarHeight with Integer object (instead of using primitive int data) to save the first value of that height difference with only one initialization, which I assume that is the height of Nav Bar.

And then in next code block, I check if next height difference is greater than the height of actual Navigation Bar in Android system (or 100 is default just in case if there is no Navigation Bar in Android system), then I subtract again with the value of systemNavigationBarHeight to get the real height of soft/virtual keyboard.

Hope this will help on someone who look up another answer.

public class MyActivity extends AppCompatActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		rootView.getViewTreeObserver()
				.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
					private Integer systemNavigationBarHeight = null;
						
					@Override
					public void onGlobalLayout() {
						int heightDifference = getHeightDifference();
						if (heightDifference > 0) {
							if (systemNavigationBarHeight == null) {
								/* Get layout height when the layout was created at first time */
								systemNavigationBarHeight = heightDifference;
							}
						} else {
							systemNavigationBarHeight = 0;
						}

						if (heightDifference > getDefaultNavigationBarHeight()) {
							/* Keyboard opened */
							int keyBoardHeight = heightDifference - systemNavigationBarHeight;
						} else {
							/* Keyboard closed */
						}
					}
		}
	}
	
	private int getHeightDifference() {
		Point screenSize = new Point();
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
			getWindowManager().getDefaultDisplay().getRealSize(screenSize);
		} else {
			getWindowManager().getDefaultDisplay().getSize(screenSize);
		}

		Rect rect = new Rect();
		rootView.getWindowVisibleDisplayFrame(rect);
		return screenSize.y - rect.bottom;
	}
	
	private int getDefaultNavigationBarHeight() {
		int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
		if (resourceId > 0) {
			return getResources().getDimensionPixelSize(resourceId);
		}
		return 100;
	}
}

Solution 13 - Android

A solution that I've found excellent for me, was to store a global bottom value, then to add a TreeView Observer and compare the new bottom value with the stored one. Using android:windowSoftInputMode="adjustResize"

private var bottom: Int = 0

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    val rect = Rect()
    this.window.decorView.getWindowVisibleDisplayFrame(rect)
    this.bottom = rect.bottom

    this.window.decorView.viewTreeObserver.addOnGlobalLayoutListener {
        
        val newRect = Rect()
        this.window.decorView.getWindowVisibleDisplayFrame(newRect)
        
        // the answer
        val keyboardHeight = this.bottom - newRect.bottom

        // also
        if (newRect.bottom < this.bottom) {
            //keyboard is open
            
        } else {
            //keyboard is hide
            
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZeeshan MirzaView Question on Stackoverflow
Solution 1 - AndroidSiebe BrouwerView Answer on Stackoverflow
Solution 2 - AndroidDave LawrenceView Answer on Stackoverflow
Solution 3 - AndroidTechfistView Answer on Stackoverflow
Solution 4 - Androidnull pointerView Answer on Stackoverflow
Solution 5 - AndroidPierreView Answer on Stackoverflow
Solution 6 - AndroidctateView Answer on Stackoverflow
Solution 7 - AndroidCristian HoldunuView Answer on Stackoverflow
Solution 8 - AndroidGemView Answer on Stackoverflow
Solution 9 - AndroidSagar GadaniView Answer on Stackoverflow
Solution 10 - AndroidWill PoitrasView Answer on Stackoverflow
Solution 11 - AndroidBarakudaView Answer on Stackoverflow
Solution 12 - Androiddamai007View Answer on Stackoverflow
Solution 13 - AndroidMihai D.View Answer on Stackoverflow