How do I detect if software keyboard is visible on Android Device or not?
There is no direct way - see http://groups.google.com/group/android-platform/browse_thread/thread/1728f26f2334c060/5e4910f0d9eb898a where Dianne Hackborn from the Android team has replied. However, you can detect it indirectly by checking if the window size changed in #onMeasure. See How to check visibility of software keyboard in Android?.
How to detect when keyboard is shown and hidden
In the ViewDidLoad method of your class set up to listen for messages about the keyboard:
// Listen for keyboard appearances and disappearances
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
Then in the methods you specify (in this case keyboardDidShow
and keyboardDidHide
) you can do something about it:
- (void)keyboardDidShow: (NSNotification *) notif{
// Do something here
}
- (void)keyboardDidHide: (NSNotification *) notif{
// Do something here
}
How to capture the virtual keyboard show/hide event in Android?
2020 Update
This is now possible:
On Android 11, you can do
view.setWindowInsetsAnimationCallback(object : WindowInsetsAnimation.Callback {
override fun onEnd(animation: WindowInsetsAnimation) {
super.onEnd(animation)
val showingKeyboard = view.rootWindowInsets.isVisible(WindowInsets.Type.ime())
// now use the boolean for something
}
})
You can also listen to the animation of showing/hiding the keyboard and do a corresponding transition.
I recommend reading Android 11 preview and the corresponding documentation
Before Android 11
However, this work has not been made available in a Compat
version, so you need to resort to hacks.
You can get the window insets and if the bottom insets are bigger than some value you find to be reasonably good (by experimentation), you can consider that to be showing the keyboard. This is not great and can fail in some cases, but there is no framework support for that.
This is a good answer on this exact question https://stackoverflow.com/a/36259261/372076. Alternatively, here's a page giving some different approaches to achieve this pre Android 11:
https://developer.salesforce.com/docs/atlas.en-us.noversion.service_sdk_android.meta/service_sdk_android/android_detecting_keyboard.htm
Note
This solution will not work for soft keyboards and
onConfigurationChanged
will not be called for soft (virtual)
keyboards.
You've got to handle configuration changes yourself.
http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange
Sample:
// from the link above
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks whether a hardware keyboard is available
if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show();
} else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show();
}
}
Then just change the visibility of some views, update a field, and change your layout file.
How to check visibility of software keyboard in 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
}
...
}
Soft keyboard open and close listener in an activity in Android
This only works when android:windowSoftInputMode
of your activity is set to adjustResize
in the manifest. You can use a layout listener to see if the root layout of your activity is resized by the keyboard.
I use something like the following base class for my activities:
public class BaseActivity extends Activity {
private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight();
int contentViewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(BaseActivity.this);
if(heightDiff <= contentViewTop){
onHideKeyboard();
Intent intent = new Intent("KeyboardWillHide");
broadcastManager.sendBroadcast(intent);
} else {
int keyboardHeight = heightDiff - contentViewTop;
onShowKeyboard(keyboardHeight);
Intent intent = new Intent("KeyboardWillShow");
intent.putExtra("KeyboardHeight", keyboardHeight);
broadcastManager.sendBroadcast(intent);
}
}
};
private boolean keyboardListenersAttached = false;
private ViewGroup rootLayout;
protected void onShowKeyboard(int keyboardHeight) {}
protected void onHideKeyboard() {}
protected void attachKeyboardListeners() {
if (keyboardListenersAttached) {
return;
}
rootLayout = (ViewGroup) findViewById(R.id.rootLayout);
rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener);
keyboardListenersAttached = true;
}
@Override
protected void onDestroy() {
super.onDestroy();
if (keyboardListenersAttached) {
rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(keyboardLayoutListener);
}
}
}
The following example activity uses this to hide a view when the keyboard is shown and show it again when the keyboard is hidden.
The xml layout:
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
And the activity:
public class TestActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_activity);
attachKeyboardListeners();
}
@Override
protected void onShowKeyboard(int keyboardHeight) {
// do things when keyboard is shown
bottomContainer.setVisibility(View.GONE);
}
@Override
protected void onHideKeyboard() {
// do things when keyboard is hidden
bottomContainer.setVisibility(View.VISIBLE);
}
}
Related Topics
How to Rotate Text for Uibutton and Uilabel in Objective-C
Drawing Class Drawing Straight Lines Instead of Curved Lines
Why Does Apple Recommend to Use Dispatch_Once for Implementing the Singleton Pattern Under Arc
Where's the Difference Between Setobject:Forkey: and Setvalue:Forkey: in Nsmutabledictionary
Ios: Keep an App Running Like a Service
How to Capitalize Each Word in a String Using Swift iOS
How to Hide Keyboard in Swift on Pressing Return Key
Tablefooterview Property Doesn't Fix the Footer at the Bottom of the Table View
Load View from an External Xib File in Storyboard
Are Nslayoutconstraints Animatable
How to Initialize/Instantiate a Custom Uiview Class with a Xib File in Swift
Present Modal View Controller in Half Size Parent Controller