How to Capture the "Virtual Keyboard Show/Hide" Event in Android

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 catch an event when soft keyboard appears

//Clicking on the text box     

edittext.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
InputMethodManager imm = (InputMethodManager) getSystemService(
INPUT_METHOD_SERVICE);
imm.showSoftInput(getCurrentFocus().getWindowToken(), //some flag here);
}

});

//Being inside the box and pressing a key
edittext.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
//If the event is a key-down event on the "enter" button
//If enter is pressed while inside the textbox
if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER)) {

InputMethodManager imm = (InputMethodManager) getSystemService(
INPUT_METHOD_SERVICE);
//Example of hiding keyboard inside enter pressed check
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);

........

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:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>

<!-- omitted for brevity -->

</ScrollView>

<LinearLayout android:id="@+id/bottomContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>

<!-- omitted for brevity -->

</LinearLayout>

</LinearLayout>

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

Android EditText, soft keyboard show/hide event?

Hi I'd used following workaround:

As far as my content view is a subclass of LinearLayout (could be any other view or view group), I'd overridden onMeasure method lilke following:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
final int actualHeight = getHeight();

if (actualHeight > proposedheight){
// Keyboard is shown
} else {
// Keyboard is hidden
}

super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

This workaround helped me to hide some controls when keyboard is showing and bring back otherwise.

Hope this would be useful.

Keyboard hide event with BACK key

You need to implement this to capture the BACK button before it is dispatched to the IME:

http://developer.android.com/reference/android/view/View.html#onKeyPreIme(int, android.view.KeyEvent)

Show/Hide Soft Keyboard event in Fragment

Sadly but true - android do not have native on software keyboard show event.

One the way handle fact that keyboard is hidden is to check entered symbols and back button press (for example textEdit will receive even back button) - but it is not flexible enough solution.

Another the possible solutions is:
Override onMeasure in activity and then notify observers (pattern Observer) - for example fragments. Fragment should subscribe and unsubscribe himself onPause onResume events. Something like that for activity code:

private class DialogActivityLayout extends LinearLayout {

public DialogActivityLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.activity_dialog, this);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int proposedHeight = MeasureSpec.getSize(heightMeasureSpec);
final int actualHeight = getHeight();

/* Layout loaded */
if (actualHeight == 0 || proposedHeight == actualHeight) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}

if (proposedHeight > actualHeight) {
DialogActivity.this.onKeyboardHide();
} else {
DialogActivity.this.onKeyboardShow();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}

I'm not sure but as I remember it works only for LinearLayout and of course activity should have adjustResize flag set (programmatically or in manifeset)

Another (I thing better approach) is to as here with globalTree observer

SoftKeyboard open and close listener in an activity in Android?

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?.



Related Topics



Leave a reply



Submit