How to check visibility of software keyboard in Android?

AndroidVisibilityAndroid Softkeyboard

Android Problem Overview


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

Android Solutions


Solution 1 - Android

NEW ANSWER added Jan 25th 2012

Since writing the below answer, someone clued me in to the existence of ViewTreeObserver and friends, APIs which have been lurking in the SDK since version 1.

Rather than requiring a custom Layout type, a much simpler solution is to give your activity's root view a known ID, say @+id/activityRoot, hook a GlobalLayoutListener into the ViewTreeObserver, and from there calculate the size diff between your activity's view root and the window size:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
        if (heightDiff > dpToPx(this, 200)) { // if more than 200 dp, it's probably a keyboard...
            // ... do something here
        }
     }
});

Using a utility such as:

public static float dpToPx(Context context, float valueInDp) {
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}

Easy!

Note: Your application must set this flag in Android Manifest android:windowSoftInputMode="adjustResize" otherwise above solution will not work.

ORIGINAL ANSWER

Yes it's possible, but it's far harder than it ought to be.

If I need to care about when the keyboard appears and disappears (which is quite often) then what I do is customize my top-level layout class into one which overrides onMeasure(). The basic logic is that if the layout finds itself filling significantly less than the total area of the window, then a soft keyboard is probably showing.

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.LinearLayout;

/*
 * LinearLayoutThatDetectsSoftKeyboard - a variant of LinearLayout that can detect when 
 * the soft keyboard is shown and hidden (something Android can't tell you, weirdly). 
 */

public class LinearLayoutThatDetectsSoftKeyboard extends LinearLayout {

	public LinearLayoutThatDetectsSoftKeyboard(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	
	public interface Listener {
		public void onSoftKeyboardShown(boolean isShowing);
	}
	private Listener listener;
	public void setListener(Listener listener) {
		this.listener = listener;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int height = MeasureSpec.getSize(heightMeasureSpec);
		Activity activity = (Activity)getContext();
		Rect rect = new Rect();
		activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
		int statusBarHeight = rect.top;
		int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
		int diff = (screenHeight - statusBarHeight) - height;
		if (listener != null) {
			listener.onSoftKeyboardShown(diff>128); // assume all soft keyboards are at least 128 pixels high
		}
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);		
	}

    }

Then in your Activity class...

public class MyActivity extends Activity implements LinearLayoutThatDetectsSoftKeyboard.Listener {
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        LinearLayoutThatDetectsSoftKeyboard mainLayout = (LinearLayoutThatDetectsSoftKeyboard)findViewById(R.id.main);
        mainLayout.setListener(this);
        ...
    }


    @Override
    public void onSoftKeyboardShown(boolean isShowing) {
        // do whatever you need to do here
    }

    ...
}

Solution 2 - Android

So hopefully this helps someone out.

The new answer that Reuben Scratton gave is great and really efficient, but it really only works if you set your windowSoftInputMode to adjustResize. If you set it to adjustPan, it's still not possible to detect whether or not the keyboard is visible using his code snippet. To work around this, I made this tiny modification to the code above.

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new 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.height();
    if (heightDiff > 0.25*activityRootView.getRootView().getHeight()) { // if more than 25% of the screen, its probably a keyboard...
        ... do something here
    }
 }
}); 

Solution 3 - Android

It has been forever in terms of computer but this question is still unbelievably relevant!

So I've taken the above answers and have combined and refined them a bit...

public interface OnKeyboardVisibilityListener {


	void onVisibilityChanged(boolean visible);
}

public final void setKeyboardListener(final OnKeyboardVisibilityListener listener) {
	final View activityRootView = ((ViewGroup) getActivity().findViewById(android.R.id.content)).getChildAt(0);

	activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

		private boolean wasOpened;

		private final int DefaultKeyboardDP = 100;

		// From @nathanielwolf answer...  Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
		private final int EstimatedKeyboardDP = DefaultKeyboardDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0);

		private final Rect r = new Rect();

		@Override
		public void onGlobalLayout() {
			// Convert the dp to pixels.
			int estimatedKeyboardHeight = (int) TypedValue
					.applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, activityRootView.getResources().getDisplayMetrics());

			// Conclude whether the keyboard is shown or not.
			activityRootView.getWindowVisibleDisplayFrame(r);
			int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
			boolean isShown = heightDiff >= estimatedKeyboardHeight;

			if (isShown == wasOpened) {
				Log.d("Keyboard state", "Ignoring global layout change...");
				return;
			}

			wasOpened = isShown;
			listener.onVisibilityChanged(isShown);
		}
	});
}

Works for me :)

NOTE: If you notice that the DefaultKeyboardDP does not fit your device play with the value and post a comment for everyone to know what should be the value... eventually we will get the correct value to fit all devices!

For more details, check out the implementation on Cyborg

Solution 4 - Android

Sorry for the late answer, but I had created a little helper class to handle open/close events with notifying listeners and other useful things, may be someone would find it helpful:

import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;

import java.util.LinkedList;
import java.util.List;

public class SoftKeyboardStateWatcher implements ViewTreeObserver.OnGlobalLayoutListener {

    public interface SoftKeyboardStateListener {
        void onSoftKeyboardOpened(int keyboardHeightInPx);
        void onSoftKeyboardClosed();
    }

    private final List<SoftKeyboardStateListener> listeners = new LinkedList<SoftKeyboardStateListener>();
    private final View activityRootView;
    private int        lastSoftKeyboardHeightInPx;
    private boolean    isSoftKeyboardOpened;

    public SoftKeyboardStateWatcher(View activityRootView) {
        this(activityRootView, false);
    }

    public SoftKeyboardStateWatcher(View activityRootView, boolean isSoftKeyboardOpened) {
        this.activityRootView     = activityRootView;
        this.isSoftKeyboardOpened = isSoftKeyboardOpened;
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    @Override
    public void onGlobalLayout() {
        final Rect r = new Rect();
        //r will be populated with the coordinates of your view that area still visible.
        activityRootView.getWindowVisibleDisplayFrame(r);

        final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
        if (!isSoftKeyboardOpened && heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
            isSoftKeyboardOpened = true;
            notifyOnSoftKeyboardOpened(heightDiff);
        } else if (isSoftKeyboardOpened && heightDiff < 100) {
            isSoftKeyboardOpened = false;
            notifyOnSoftKeyboardClosed();
        }
    }

    public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) {
        this.isSoftKeyboardOpened = isSoftKeyboardOpened;
    }

    public boolean isSoftKeyboardOpened() {
        return isSoftKeyboardOpened;
    }

    /**
     * Default value is zero {@code 0}.
     *
     * @return last saved keyboard height in px
     */
    public int getLastSoftKeyboardHeightInPx() {
        return lastSoftKeyboardHeightInPx;
    }

    public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
        listeners.add(listener);
    }

    public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
        listeners.remove(listener);
    }

    private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) {
        this.lastSoftKeyboardHeightInPx = keyboardHeightInPx;

        for (SoftKeyboardStateListener listener : listeners) {
            if (listener != null) {
                listener.onSoftKeyboardOpened(keyboardHeightInPx);
            }
        }
    }

    private void notifyOnSoftKeyboardClosed() {
        for (SoftKeyboardStateListener listener : listeners) {
            if (listener != null) {
                listener.onSoftKeyboardClosed();
            }
        }
    }
}

Usage example:

final SoftKeyboardStateWatcher softKeyboardStateWatcher 
    = new SoftKeyboardStateWatcher(findViewById(R.id.activity_main_layout);

// Add listener
softKeyboardStateWatcher.addSoftKeyboardStateListener(...);
// then just handle callbacks

Solution 5 - Android

Some improvements to avoid wrongly detect the visibility of soft keyboard on high density devices:

  1. Threshold of height difference should be defined as 128 dp, not 128 pixels.
    Refer to Google design doc about Metrics and Grid, 48 dp is comfortable size for touch object and 32 dp is minimum for buttons. Generic soft keyboard should include 4 rows of key buttons, so minimum keyboard height should be: 32 dp * 4 = 128 dp, that means threshold size should transfer to pixels by multiply device density. For xxxhdpi devices (density 4), the soft keyboard height threshold should be 128 * 4 = 512 pixels.

  2. Height difference between root view and its visible area:
    root view height - status bar height - visible frame height = root view bottom - visible frame bottom, since status bar height equal to the top of root view visible frame.

     private final String TAG = "TextEditor";
     private TextView mTextEditor;
    
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_editor);
         mTextEditor = (TextView) findViewById(R.id.text_editor);
         mTextEditor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
             @Override
             public void onGlobalLayout() {
                 isKeyboardShown(mTextEditor.getRootView());
             }
         });
     }
    
     private boolean isKeyboardShown(View rootView) {
         /* 128dp = 32dp * 4, minimum button height 32dp and generic 4 rows soft keyboard */
         final int SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128;
    
         Rect r = new Rect();
         rootView.getWindowVisibleDisplayFrame(r);
         DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
         /* heightDiff = rootView height - status bar height (r.top) - visible frame height (r.bottom - r.top) */
         int heightDiff = rootView.getBottom() - r.bottom;
         /* Threshold size: dp to pixels, multiply with display density */
         boolean isKeyboardShown = heightDiff > SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD * dm.density;
    
         Log.d(TAG, "isKeyboardShown ? " + isKeyboardShown + ", heightDiff:" + heightDiff + ", density:" + dm.density
                 + "root view height:" + rootView.getHeight() + ", rect:" + r);
    
         return isKeyboardShown;
     }
    

Solution 6 - Android

Wow, We have Good news Android Geeks. And its time to say goodbye to the old way. First I will add official release note to read and know more about these methods/ classes, and then we will see these amazing methods/ classes

Breaking Note: Do not add these into your release apps, until these classes/ methods are released

> How to check keyboard visibility

val insets = ViewCompat.getRootWindowInsets(view)
val isKeyboardVisible = insets.isVisible(Type.ime())

Few other utilities

> How to get the height of Keyboard

val insets = ViewCompat.getRootWindowInsets(view)
val keyboardHeight = insets.getInsets(Type.ime()).bottom

> How to show/ hide the keyboard

val controller = view.windowInsetsController

// Show the keyboard
controller.show(Type.ime())

// Hide the keyboard
controller.hide(Type.ime())

Note: WindowInsetsController added in API-30, so wait till backward compatible class is not available.

> How to listen to keyboard hide/ show event

ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
    val isKeyboardVisible = insets.isVisible(Type.ime())
    if (isKeyboardVisible) {
        // Do it when keyboard is being shown
    } else {
        // Do it when keyboard is hidden
    }

    // Return the insets to keep going down this event to the view hierarchy
    insets
}

Solution 7 - Android

I used a little time to figure this out... I ran it some CastExceptions, but figured out that you can replace you LinearLayout in the layout.xml with the name of the class.

Like this:

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/llMaster">

<com.ourshoppingnote.RelativeLayoutThatDetectsSoftKeyboard android:background="@drawable/metal_background"
	android:layout_width="fill_parent" android:layout_height="fill_parent"
	android:id="@+id/rlMaster" >
	<LinearLayout android:layout_width="fill_parent"
		android:layout_height="1dip" android:background="@drawable/line"></LinearLayout>
	
          ....
		
</com.ourshoppingnote.RelativeLayoutThatDetectsSoftKeyboard>	

 	
</LinearLayout>

That way you do not run into any cast issues.

... and if you don't want to do this on every page, I recommend that you use "MasterPage in Android". See the link here: http://jnastase.alner.net/archive/2011/01/08/ldquomaster-pagesrdquo-in-android.aspx

Solution 8 - Android

The idea is, if you need to hide your keyboard and check soft input state at the same time, use the following solution:

public boolean hideSoftInput() {
	InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
	return imm.hideSoftInputFromWindow(mViewPager.getWindowToken(), 0);
}

This method returns true if keyboard was shown before hiding.

Solution 9 - Android

Checking the height of elements is not reliable because some keyboards like WifiKeyboard have zero height.

Instead, you can use the callback result of showSoftInput() and hideSoftInput() to check for the status of the keyboard. Full details and example code at

https://rogerkeays.com/how-to-check-if-the-software-keyboard-is-shown-in-android

Solution 10 - Android

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

Solution 11 - Android

You can observe softkeyboard's hide by using activity's decorView.

public final class SoftKeyboardUtil {
    public static final String TAG = "SoftKeyboardUtil";
    public static void observeSoftKeyBoard(Activity activity , final OnSoftKeyBoardHideListener listener){
	    final View decorView = activity.getWindow().getDecorView();
	    decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
		    @Override
		    public void onGlobalLayout() {
			    Rect rect = new Rect();
			    decorView.getWindowVisibleDisplayFrame(rect);
			    int displayHight = rect.bottom - rect.top;
			    int hight = decorView.getHeight();
			    boolean hide = (double)displayHight / hight > 0.8 ;
			    if(Log.isLoggable(TAG, Log.DEBUG)){
				    Log.d(TAG ,"DecorView display hight = "+displayHight);
				    Log.d(TAG ,"DecorView hight = "+ hight);
				    Log.d(TAG, "softkeyboard visible = " + !hide);
			    }
			
			    listener.onSoftKeyBoardVisible(!hide);
			    
		    }
	    });
    }



    public interface OnSoftKeyBoardHideListener{
	    void onSoftKeyBoardVisible(boolean visible);
    }
}

Solution 12 - Android

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.

Solution 13 - Android

There's a hidden method can help for this, InputMethodManager.getInputMethodWindowVisibleHeight. But I don't know why it's hidden.

import android.content.Context
import android.os.Handler
import android.view.inputmethod.InputMethodManager

class SoftKeyboardStateWatcher(private val ctx: Context) {
  companion object {
  	private const val DELAY = 10L
  }

  private val handler = Handler()
  private var isSoftKeyboardOpened: Boolean = false

  private val height: Int
    get() {
      val imm = ctx.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
      val method = imm.javaClass.getMethod("getInputMethodWindowVisibleHeight")
      method.isAccessible = true
      return method.invoke(imm) as Int
    }

  private val task: Runnable by lazy {
    Runnable {
      start()
      if (!isSoftKeyboardOpened && height > 0) {
        isSoftKeyboardOpened = true
        notifyOnSoftKeyboardOpened(height)
      } else if (isSoftKeyboardOpened && height == 0) {
        isSoftKeyboardOpened = false
        notifyOnSoftKeyboardClosed()
      }
    }
  }

  var listener: SoftKeyboardStateListener? = null

  interface SoftKeyboardStateListener {
    fun onSoftKeyboardOpened(keyboardHeightInPx: Int)
    fun onSoftKeyboardClosed()
  }

  fun start() {
    handler.postDelayed(task, DELAY)
  }

  fun stop() {
    handler.postDelayed({
      if (!isSoftKeyboardOpened) handler.removeCallbacks(task)
    }, DELAY * 10)
  }

  private fun notifyOnSoftKeyboardOpened(keyboardHeightInPx: Int) {
    listener?.onSoftKeyboardOpened(keyboardHeightInPx)
  }

  private fun notifyOnSoftKeyboardClosed() {
    listener?.onSoftKeyboardClosed()
  }
}

Solution 14 - Android

I found that a combination of @Reuben_Scratton's method along with @Yogesh's method seems to work best. Combining their methods would yield something like this:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
  @Override
  public void onGlobalLayout() {
    if (getResources().getConfiguration().keyboardHidden == Configuration.KEYBOARDHIDDEN_NO) { // Check if keyboard is not hidden
       // ... do something here
    }
  }
});

Solution 15 - Android

I used a slight variant of Reuban's answer, which proved to be more helpful in certain circumstances, especially with high resolution devices.

final View activityRootView = findViewById(android.R.id.content);
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
                }
            }
        });

Solution 16 - Android

None of these solutions will work for Lollipop as is. In Lollipop activityRootView.getRootView().getHeight() includes the height of the button bar, while measuring the view does not. I've adapted the best/simplest solution above to work with Lollipop.

    final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new 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);
    Resources res = getResources();
    // The status bar is 25dp, use 50dp for assurance
    float maxDiff =
        TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, res.getDisplayMetrics());

    //Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      float buttonBarHeight =
          TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48, res.getDisplayMetrics());
      maxDiff += buttonBarHeight;
    }
    if (heightDiff > maxDiff) { // if more than 100 pixels, its probably a keyboard...
      ...do something here
    }
  }
});

Solution 17 - Android

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.

Solution 18 - Android

It has been forever in terms of the computer but this question is still unbelievably relevant! So I've taken the above answers and have combined and refined them a bit...

public interface OnKeyboardVisibilityListener {
    void onVisibilityChanged(boolean visible);
}

public final void setKeyboardListener(final OnKeyboardVisibilityListener listener) {
    final View activityRootView = ((ViewGroup) getActivity().findViewById(android.R.id.content)).getChildAt(0);
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

        private boolean wasOpened;

    private final Rect r = new Rect();

        @Override
        public void onGlobalLayout() {
            activityRootView.getWindowVisibleDisplayFrame(r);

            int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
            boolean isOpen = heightDiff > 100;
            if (isOpen == wasOpened) {
                logDebug("Ignoring global layout change...");
                return;
            }

            wasOpened = isOpen;
            listener.onVisibilityChanged(isOpen);
        }
    });
}

It works for me.

Solution 19 - Android

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

Solution 20 - Android

Don't make any hard code. Best way is you have to resize your views while on Get Focus on EditText with KeyBord Show. You can do this adding resize property on activity into Manifest file using below code.

android:windowSoftInputMode="adjustResize"

Solution 21 - Android

My answer is basically the same as Kachi's answer, but I wrapped it into a nice helper class to clean up the way it's used throughout my app.

import android.app.Activity;
import android.app.Fragment;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;

/**
 * Detects Keyboard Status changes and fires events only once for each change
 */
public class KeyboardStatusDetector {
    KeyboardVisibilityListener visibilityListener;

    boolean keyboardVisible = false;

    public void registerFragment(Fragment f) {
        registerView(f.getView());
    }

    public void registerActivity(Activity a) {
        registerView(a.getWindow().getDecorView().findViewById(android.R.id.content));
    }

    public KeyboardStatusDetector registerView(final View v) {
        v.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();
                v.getWindowVisibleDisplayFrame(r);

                int heightDiff = v.getRootView().getHeight() - (r.bottom - r.top);
                if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
                    /** Check this variable to debounce layout events */
                    if(!keyboardVisible) {
                        keyboardVisible = true;
                        if(visibilityListener != null) visibilityListener.onVisibilityChanged(true);
                    }
                } else {
                    if(keyboardVisible) {
                        keyboardVisible = false;
                        if(visibilityListener != null) visibilityListener.onVisibilityChanged(false);
                    }
                }
            }
        });

        return this;
    }

    public KeyboardStatusDetector setVisibilityListener(KeyboardVisibilityListener listener) {
        visibilityListener = listener;
        return this;
    }

    public static interface KeyboardVisibilityListener {
        public void onVisibilityChanged(boolean keyboardVisible);
    }
}

You can use this to detect keyboard changes anywhere throughout the app like this:

    new KeyboardStatusDetector()
            .registerFragment(fragment)  //register to a fragment 
            .registerActivity(activity)  //or register to an activity
            .registerView(view)          //or register to a view
            .setVisibilityListener(new KeyboardVisibilityListener() {
                @Override
                public void onVisibilityChanged(boolean keyboardVisible) {
                    if(keyboardVisible) {
                       //Do stuff for keyboard visible
                    }else {
                       //Do stuff for keyboard hidden
                    }
                }
            });

Note: only use one of the "register" calls. They all work the same and are only there for convenience

Solution 22 - Android

i think this method will help you to find out is keybord is visible or not.

 public Boolean isSoftKeyBoardVisible(){
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);

    if (imm.isAcceptingText()) {
        Log.d(TAG,"Software Keyboard was shown");
        return true;
    } else {
        Log.d(TAG,"Software Keyboard was not shown");
        return false;
    }

}

Solution 23 - Android

you can try this, work great for me:

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

if (imm.isAcceptingText()) {
    //Software Keyboard was shown..
} else {
    //Software Keyboard was not shown..
}

Solution 24 - Android

I was having difficulty maintaining keyboard state when changing orientation of fragments within a viewpager. I'm not sure why, but it just seems to be wonky and acts differently from a standard Activity.

To maintain keyboard state in this case, first you should add android:windowSoftInputMode = "stateUnchanged" to your AndroidManifest.xml. You may notice, though, that this doesn't actually solve the entire problem -- the keyboard didn't open for me if it was previously opened before orientation change. In all other cases, the behavior seemed to be correct.

Then, we need to implement one of the solutions mentioned here. The cleanest one I found was George Maisuradze's--use the boolean callback from hideSoftInputFromWindow:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
return imm.hideSoftInputFromWindow(mViewPager.getWindowToken(), 0);

I stored this value in my Fragment's onSaveInstanceState method and retrieved it onCreate. Then, I forcibly showed the keyboard in onCreateView if it had a value of true (it returns true if the keyboard is visible before actually hiding it prior to the Fragment destruction).

Solution 25 - Android

according to the doc.. https://developer.android.com/reference/androidx/core/view/WindowInsetsCompat

check release note.. https://developer.android.com/jetpack/androidx/releases/core#1.5.0-alpha02

To get the current keyboard visibility, you can use getRootWindowInsets, and then call the isVisible() function, passing in the IME type.

val windowinsetscompat = ViewCompat.getRootWindowInsets(view)
val imeVisible = windowinsetscompat.isVisible(Type.ime())

there is also listener for changes OnApplyWindowInsetsListener

ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
    val imeVisible = insets.isVisible(Type.ime())
}

Solution 26 - Android

Here's my solution, and it works. Instead of looking for pixel size just check that the height of the content view has changed or not:

// Scroll to the latest comment whenever the keyboard is shown
commentsContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        private int oldHeight;

        @Override
        public void onGlobalLayout() {
            int newHeight = commentsContent.getMeasuredHeight();
            if (newHeight < oldHeight) {
                // Check for the keyboard showing in case the height difference
                // is a result of orientation change
                if (isSoftKeyboardShowing(CommentsActivity.this)) {
                    // Keyboard is showing so scroll to the latest comment
                    scrollToLatestComment();
                }
            }
            oldHeight = newHeight;
        }

    });


public static boolean isSoftKeyboardShowing(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    return inputMethodManager.isActive();
}

Solution 27 - Android

There is a direct method to find this out. And, it does not require any Layout changes.
So, it works in immersive fullscreen mode, too.

The trick is that you try to hide or show the soft keyboard and capture the result of that try.
No panic, this does not really show or hide the keyboard. We just ask for the state.

To stay up-to-date, you can simply repeat the operation, e.g. every 200 milliseconds, using a Handler.

You find an implementation here: https://stackoverflow.com/a/27567074/2525452

Solution 28 - Android

After understanding some of the issues with different resolutions, I decided to use a relative size. As I noticed the difference between visible and hidden states is about 30%. So I decided to replace 128 PX with 0.3.

And I added this class listener to notify of any change.

Here is my version

import android.app.*;
import android.graphics.*;
import android.view.*;

public class SoftKeyboardState {
  public static final int HIDDEN = 0, VISIBLE = 1;
  private OnKeyboardStateChangedListener listener;
  private View decorView;

  public SoftKeyboardState(Activity activity) {
	this.decorView = activity.findViewById(android.R.id.content);
	initKeyboardListener();
  }

  private void initKeyboardListener() {
	decorView.getViewTreeObserver().addOnGlobalLayoutListener(
	  new ViewTreeObserver.OnGlobalLayoutListener(){
		private final Rect windowVisibleDisplayFrame = new Rect();
		private int lastVisibleDecorViewHeight;

		@Override
		public void onGlobalLayout() {
		  decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame);
		  final int visibleDecorViewHeight = windowVisibleDisplayFrame.height();

		  if (lastVisibleDecorViewHeight != 0) {
			if ((lastVisibleDecorViewHeight > visibleDecorViewHeight) && (lastVisibleDecorViewHeight / visibleDecorViewHeight >= 0.3f)) {
			  // visible
			  if (listener != null)listener.onKeyboardStateChanged(VISIBLE);
			} else if ((lastVisibleDecorViewHeight < visibleDecorViewHeight) && (visibleDecorViewHeight / lastVisibleDecorViewHeight >= 0.3f)) {
			  // hidden
			  if (listener != null)listener.onKeyboardStateChanged(HIDDEN);
			}
		  }
		  lastVisibleDecorViewHeight = visibleDecorViewHeight;
		}
	  });
  }

  public void setOnKeyboardStateChangedListener(OnKeyboardStateChangedListener listener) {
	this.listener = listener;
  }

  public interface OnKeyboardStateChangedListener {
	public void onKeyboardStateChanged(int state);
  }
}

Solution 29 - Android

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.

Solution 30 - Android

Reuben Scratton's new answer (calculate the HeightDiff int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight(); ) will not work in activity if you set the translucent status bar mode.

if you use translucent status bar , activityRootView.getHeight() will never change weather the soft keyboard is visible. it will always return the height of activity and status bar.

For example, Nexus 4, Android 5.0.1, set android:windowTranslucentStatus to true, it will return 1184 forever, even the ime have opend. If you set android:windowTranslucentStatus to false, it will return Height correctly, if ime invisible,it return 1134(not include the status bar)。close the ime, it will return 5xx maybe (depends on ime's height)

I don't know weather this is a bug, I've try on 4.4.4 and 5.0.1, the result is same.

So, up to now, the second most agreed answer, Kachi's solution will be the most safe way to calcute the height of ime. Here's a copy:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new        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 > 100) { // if more than 100 pixels, its probably a keyboard...
    ... do something here
    }
 }
}); 

Solution 31 - Android

A method that doesn't need a LayoutListener

In my case, I would like to save the state of the keyboard before replacing my Fragment. I call the method hideSoftInputFromWindow from onSaveInstanceState, which closes the keyboard and returns me whether the keyboard was visible or not.

This method is straightforward but may change the state of your keyboard.

Solution 32 - Android

This solution may re-opens the keyboard but it works.

InputMethodManager inputManager = ( (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE) );

private boolean isKeyboardShowing() {

	boolean isKeyboardShowing = inputManager.hideSoftInputFromWindow(irrelevantView.getWindowToken(), 0);
	if (isKeyboardShowing) {
		inputManager.showSoftInput(this.getCurrentFocus(), 0);
	}
	return isKeyboardShowing;
}

Solution 33 - Android

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,

Solution 34 - Android

if (keyopen())
{
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY,0);            
}

The above function is what I use to check if a Keyboard is visible. If it is, then I close it.

Below shows the two methods required.

First, define the workable Window height in onCreate.

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

//  add to onCreate method
    Rect rectgle= new Rect();
    Window window= getWindow();
    window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
    sheight= rectgle.bottom;
//

} 

Then, add a boolean method that gets the Window height at that instance. If it does not match the original (assuming you are not changing it along the way...) then, the keyboard is open.

public boolean keyopen()
{
    Rect rectgle= new Rect();
    Window window= getWindow();
    window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
    int curheight= rectgle.bottom;

    if (curheight!=sheight)
    {
        return true;
    }
    else
    {
        return false;
    }
}

Frotz!

Solution 35 - Android

I know how exact you can determine if keyboard is hidden or not.

public int getStatusBarHeight() {
	int result = 0;
	int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
	if (resourceId > 0) {
		result = getResources().getDimensionPixelSize(resourceId);
	}
	return result;
}

public int getNavigationBarHeight() {
	int result = 0;
	int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
	if (resourceId > 0) {
		result = getResources().getDimensionPixelSize(resourceId);
	}
	return result;
}

public boolean isKeyboardHidden() {
	int delta = mRootView.getRootView().getHeight() - mRootView.getHeight() - getNavigationBarHeight() - getStatusBarHeight()
			- getSupportActionBar().getHeight();
	return delta <= 0;
}

This works for tablets. When navigationbar is shown horizontally.

Solution 36 - Android

You can use InputMethodManager.isActive method that returns true if the keyboard is visible:

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

You can also see if the keyboard is active in a specific view:

    imm.isActive(View v);

Solution 37 - Android

The solution provided by Reuben Scratton and Kachi seems to rely on the pixel density of the devices, if you have a high density device the height difference can be bigger than 100 even with the keyboard down. A little work around that would be to see the initial height difference (with keyboard down) and then compare with the current difference.

boolean isOpened = false;
int firstHeightDiff = -1;

public void setListenerToRootView(){
    final View activityRootView = getActivity().getWindow().getDecorView().findViewById(android.R.id.content);
    Rect r = new Rect();
    activityRootView.getWindowVisibleDisplayFrame(r);
    firstHeightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (isAdded()) {
                Rect r = new Rect();
                activityRootView.getWindowVisibleDisplayFrame(r);
                int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
                isOpened = heightDiff>firstHeightDiff+100;
                if (isAdded())
                    if(isOpened) {
                        //TODO stuff for when it is up
                    } else {
                        //TODO stuf for when it is down
                    }
            }
        }
    });
}

Solution 38 - Android

Here is a workaround to know if softkeyboard is visible.

  1. Check for running services on the system using ActivityManager.getRunningServices(max_count_of_services);
  2. From the returned ActivityManager.RunningServiceInfo instances, check clientCount value for soft keyboard service.
  3. The aforementioned clientCount will be incremented every time, the soft keyboard is shown. For example, if clientCount was initially 1, it would be 2 when the keyboard is shown.
  4. On keyboard dismissal, clientCount is decremented. In this case, it resets to 1.

Some of the popular keyboards have certain keywords in their classNames:

Google AOSP = IME
Swype = IME
Swiftkey = KeyboardService
Fleksy = keyboard
Adaptxt = IME (KPTAdaptxtIME)
Smart = Keyboard (SmartKeyboard)

From ActivityManager.RunningServiceInfo, check for the above patterns in ClassNames. Also, ActivityManager.RunningServiceInfo's clientPackage=android, indicating that the keyboard is bound to system.

The above mentioned information could be combined for a strict way to find out if soft keyboard is visible.

Solution 39 - Android

This code works great nice

use this class for root view:

public class KeyboardConstraintLayout extends ConstraintLayout {

private KeyboardListener keyboardListener;
private EditText targetEditText;
private int minKeyboardHeight;
private boolean isShow;

public KeyboardConstraintLayout(Context context) {
    super(context);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height);
}

public KeyboardConstraintLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height);
}

public KeyboardConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (!isInEditMode()) {
        Activity activity = (Activity) getContext();
        @SuppressLint("DrawAllocation")
        Rect rect = new Rect();
        getWindowVisibleDisplayFrame(rect);

        int statusBarHeight = rect.top;
        int keyboardHeight = activity.getWindowManager().getDefaultDisplay().getHeight() - (rect.bottom - rect.top) - statusBarHeight;

        if (keyboardListener != null && targetEditText != null && targetEditText.isFocused()) {
            if (keyboardHeight > minKeyboardHeight) {
                if (!isShow) {
                    isShow = true;
                    keyboardListener.onKeyboardVisibility(true);
                }
            }else {
                if (isShow) {
                    isShow = false;
                    keyboardListener.onKeyboardVisibility(false);
                }
            }
        }
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

public boolean isShowKeyboard() {
    return isShow;
}

public void setKeyboardListener(EditText targetEditText, KeyboardListener keyboardListener) {
    this.targetEditText = targetEditText;
    this.keyboardListener = keyboardListener;
}

public interface KeyboardListener {
    void onKeyboardVisibility (boolean isVisible);
}

}

and set keyboard listener in activity or fragment:

    rootLayout.setKeyboardListener(targetEditText, new KeyboardConstraintLayout.KeyboardListener() {
    @Override
    public void onKeyboardVisibility(boolean isVisible) {

    }
});

Solution 40 - Android

Maybe this will help you:

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

Solution 41 - Android

Referring to this answer by @TacB0sS I have developed one class in Kotlin. Hope this will be helpful. Let me know if it requires some improvement.

class KeyboardVisibilityObserver(val layRootContainer: View?, val keyboardVisibilityListener: KeyboardVisibilityListener?) {
    var isKeyboardOpen = false
        private set

    private var keyBoardObserver = object : ViewTreeObserver.OnGlobalLayoutListener {

        private val DefaultKeyboardDP = 100

        // Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
        private val EstimatedKeyboardDP = DefaultKeyboardDP + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 48 else 0

        private val r = Rect()

        override fun onGlobalLayout() {
            if (layRootContainer != null) {
                // Convert the dp to pixels.
                val estimatedKeyboardHeight = TypedValue
                        .applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP.toFloat(), layRootContainer.resources.displayMetrics).toInt()

                // Conclude whether the keyboard is shown or not.
                layRootContainer.getWindowVisibleDisplayFrame(r)
                val heightDiff = layRootContainer.rootView.height - (r.bottom - r.top)
                val isShown = heightDiff >= estimatedKeyboardHeight

                if (isShown == isKeyboardOpen) {
                    //	Log.d("Keyboard state", "Ignoring global layout change...");
                    return
                }

                isKeyboardOpen = isShown

                keyboardVisibilityListener?.onKeyboardVisibilityChanged(isKeyboardOpen)
            }
        }
    }

    init {
        layRootContainer?.viewTreeObserver?.addOnGlobalLayoutListener(keyBoardObserver)
    }

    // call this in onDestroy
    fun removeObserver(){
        layRootContainer?.viewTreeObserver?.removeOnGlobalLayoutListener(keyBoardObserver)
    }

    interface KeyboardVisibilityListener {
        fun onKeyboardVisibilityChanged(isKeyboardOpen: Boolean)
    }
}

Solution 42 - Android

In addition to the correct answer I had to add this at the end of the onCreateView when using a webview inside a fragment.

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

May be is because I am running a Webview inside a fragment or maybe a new behavior on API 30, my issue was that the height of the fragment was never altered even if the keyboard was being shown.

So for Fragment the entire code should be

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = super.onCreateView(inflater, container, savedInstanceState);
    //mWebView.postUrl("https://www.google.com/");
    final View activityRootView = view;
    layoutListener = 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);
            // This variable was created only for Debug purposes and 
            // to see the height change when clicking on a field inside mWebView
            int screenHeight = activityRootView.getRootView().getHeight();
            Log.d("onGlobalLayout", "rect: " + r.toString());
            Log.d("onGlobalLayout", "screenHeight: " + screenHeight);

            //The difference on the heights from bottom to top and on the root height
            int heightDiff = screenHeight - (r.bottom - r.top);
            Log.d("onGlobalLayout", "heightDiff: " + heightDiff);

            //I suggest to put 250 on resources to have better order
            float dpx = dpToPx(getActivity(), 250);

            if (previousHeightDiff != heightDiff) {
                if (heightDiff > dpx) {
                    isSoftKeyboardPresent = true;
                } else {
                    isSoftKeyboardPresent = false;
                }
                previousHeightDiff = heightDiff;
            }
        }
    };
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
    getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
    return view;
}

private static float dpToPx(Context context, float valueInDp) {
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}

Solution 43 - Android

This is probably not suitable for production because it will open the keyboard. Note that the boolean returned by similar functions is not specified in the API and are therefore unreliable. Refer to the documentation here...

https://developer.android.com/reference/android/view/inputmethod/InputMethodManager#showSoftInput(android.view.View,%20int,%20android.os.ResultReceiver)

public boolean showSoftInput (View view, 
            int flags, 
            ResultReceiver resultReceiver)

Note that this method takes a ResultReceiver. It can get the results: RESULT_UNCHANGED_SHOWN, RESULT_UNCHANGED_HIDDEN, RESULT_SHOWN, or RESULT_HIDDEN. If you get RESULT_UNCHANGED_SHOWN, the keyboard was visible. If you need it to stay closed if it was closed, you will need to close it.

Solution 44 - Android

View#setOnApplyWindowInsetsListener can be used to get window insets callback

public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
    getListenerInfo().mOnApplyWindowInsetsListener = listener;
}

//OnApplyWindowInsetsListener
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);

And boolean keyboardVisible = insets.isVisible(WindowInsets.Type.ime()) can give the visibility state.

Solution 45 - Android

The InputMethodManager has information about the soft keyboard. You get it from an activity via:

((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))

You might play around with that to see what it can tell you. You can use it to show or hide the soft input...

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
QuestionfhuchoView Question on Stackoverflow
Solution 1 - AndroidReuben ScrattonView Answer on Stackoverflow
Solution 2 - AndroidKachiView Answer on Stackoverflow
Solution 3 - AndroidTacB0sSView Answer on Stackoverflow
Solution 4 - AndroidArtem ZinnatullinView Answer on Stackoverflow
Solution 5 - AndroidOrchard CafeView Answer on Stackoverflow
Solution 6 - AndroidPankaj KumarView Answer on Stackoverflow
Solution 7 - AndroidJanus Kamp HansenView Answer on Stackoverflow
Solution 8 - AndroidGeorge MaisuradzeView Answer on Stackoverflow
Solution 9 - AndroidRoger KeaysView Answer on Stackoverflow
Solution 10 - AndroidMGKView Answer on Stackoverflow
Solution 11 - AndroidZebulon LiView Answer on Stackoverflow
Solution 12 - AndroidnikisView Answer on Stackoverflow
Solution 13 - AndroidKevin DuView Answer on Stackoverflow
Solution 14 - AndroidcbradleyView Answer on Stackoverflow
Solution 15 - AndroidPearsonArtPhotoView Answer on Stackoverflow
Solution 16 - AndroidnathanielwolfView Answer on Stackoverflow
Solution 17 - AndroidN JayView Answer on Stackoverflow
Solution 18 - AndroidRoselyn SofferView Answer on Stackoverflow
Solution 19 - AndroidOfek AsheryView Answer on Stackoverflow
Solution 20 - AndroidRahul MandaliyaView Answer on Stackoverflow
Solution 21 - AndroidbillylindemanView Answer on Stackoverflow
Solution 22 - AndroidJohn smithView Answer on Stackoverflow
Solution 23 - AndroidIRvanFauziEView Answer on Stackoverflow
Solution 24 - AndroidQuantum DotView Answer on Stackoverflow
Solution 25 - AndroidJaydeep chatrolaView Answer on Stackoverflow
Solution 26 - AndroidMeanmanView Answer on Stackoverflow
Solution 27 - AndroidfiesView Answer on Stackoverflow
Solution 28 - AndroidFrancis Nduba NumbiView Answer on Stackoverflow
Solution 29 - Androidceph3usView Answer on Stackoverflow
Solution 30 - AndroidLoyeaView Answer on Stackoverflow
Solution 31 - AndroidGordakView Answer on Stackoverflow
Solution 32 - AndroidbaphoView Answer on Stackoverflow
Solution 33 - AndroidFran CeriuView Answer on Stackoverflow
Solution 34 - AndroidBelbozView Answer on Stackoverflow
Solution 35 - AndroidValentin BaryshevView Answer on Stackoverflow
Solution 36 - AndroidRicardo A.View Answer on Stackoverflow
Solution 37 - AndroidericmguimaraesView Answer on Stackoverflow
Solution 38 - AndroidSatishkumarView Answer on Stackoverflow
Solution 39 - Androidsaleh gholamianView Answer on Stackoverflow
Solution 40 - AndroidPK ChaharView Answer on Stackoverflow
Solution 41 - AndroidChitrangView Answer on Stackoverflow
Solution 42 - AndroidCésar BermúdezView Answer on Stackoverflow
Solution 43 - AndroidJohn GlenView Answer on Stackoverflow
Solution 44 - AndroidShailendra YadavView Answer on Stackoverflow
Solution 45 - AndroidCheryl SimonView Answer on Stackoverflow