45

Is it possible to catch the event that Soft Keyboard was shown or hidden for EditText?

Nirav Dangi
  • 3,517
  • 4
  • 47
  • 60
shkim
  • 1,163
  • 3
  • 16
  • 24
  • Have you solved the issue? Could you please share your experience? – woodshy Jun 12 '11 at 13:00
  • 1
    Although this is an old post, this answer in a similar context is more appropriate: http://stackoverflow.com/questions/4312319/howto-capture-the-virtual-keyboard-show-hide-event-in-android/4365637#4365637 – Pedro Loureiro Aug 08 '11 at 08:02
  • 3
    This is a better solution http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android – Zain Ali Sep 14 '12 at 07:50

7 Answers7

30

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.

danb
  • 9,613
  • 13
  • 57
  • 75
woodshy
  • 4,007
  • 3
  • 19
  • 20
  • 1
    where does one add this override? I've a SherlockActivty inflated from a LinearLayout but keep getting that the method is not defined for the class – David Homes Aug 20 '12 at 20:04
  • @dhomes it's not method of `Activity`. It's method of `View`. Create your custom `View` and override this method. – Dmitry Zaytsev Nov 26 '12 at 08:11
  • On some devices (eg. Samsung), the predictive text feature causes issues with this solution. I worked around this by setting the inputType on my edittexts to "textVisiblePassword" to disable it. – adamdport Dec 09 '14 at 15:31
18

There actually isn't such an event to catch. The IME is simply showing and hiding its window; the feedback you get from this is the window manager causing your own window's content to resize if you have put it in resize mode.

hackbod
  • 88,517
  • 16
  • 135
  • 152
4

I solved this issue by using onGlobalLayoutListener :

 final View activityRootView = findViewById(R.id.top_root);
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();

                if (heightDiff > 100) {
                    // keyboard is up
                } else {
                    // keyboard is down
                }
            }
        });

Here activityRootView is your Activity's root view.

Varun Verma
  • 672
  • 7
  • 13
2

In my case I wanted to hide a bottom bar when softkeyboard was shown. I considered best to just hide the bar when layout had less than a percent size of normal layout size. So I used this solution that works fine considering that soft keyboard usually takes 20% or more screen height. Just change the percent constant by any value you may think is ok. It needs attribute android:windowSoftInputMode="adjustResize" in manifest and layout must be the root to work.

Extend from any layout you may want instead of RelativeLayout.

public class SoftKeyboardLsnedRelativeLayout extends RelativeLayout {
    private boolean isKeyboardShown = false;
    private List<SoftKeyboardLsner> lsners=new ArrayList<SoftKeyboardLsner>();
    private float layoutMaxH = 0f; // max measured height is considered layout normal size
    private static final float DETECT_ON_SIZE_PERCENT = 0.8f;

    public SoftKeyboardLsnedRelativeLayout(Context context) {
        super(context);
    }

    public SoftKeyboardLsnedRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @SuppressLint("NewApi")
    public SoftKeyboardLsnedRelativeLayout(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int newH = MeasureSpec.getSize(heightMeasureSpec);
        if (newH > layoutMaxH) {
            layoutMaxH = newH;
        }
        if (layoutMaxH != 0f) {
            final float sizePercent = newH / layoutMaxH;
            if (!isKeyboardShown && sizePercent <= DETECT_ON_SIZE_PERCENT) {
                isKeyboardShown = true;
                for (final SoftKeyboardLsner lsner : lsners) {
                    lsner.onSoftKeyboardShow();
                }
            } else if (isKeyboardShown && sizePercent > DETECT_ON_SIZE_PERCENT) {
                isKeyboardShown = false;
                for (final SoftKeyboardLsner lsner : lsners) {
                    lsner.onSoftKeyboardHide();
                }
            }
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public void addSoftKeyboardLsner(SoftKeyboardLsner lsner) {
        lsners.add(lsner);
    }

    public void removeSoftKeyboardLsner(SoftKeyboardLsner lsner) {
        lsners.remove(lsner);
    }

    // Callback
    public interface SoftKeyboardLsner {
        public void onSoftKeyboardShow();
        public void onSoftKeyboardHide();
    }
}

Example:

layout/my_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<yourclasspackage.SoftKeyboardLsnedRelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/myLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    ...
</yourclasspackage.SoftKeyboardLsnedRelativeLayout>

MyActivity.java

public class MyActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_layout);
        SoftKeyboardLsnedRelativeLayout layout = (SoftKeyboardLsnedRelativeLayout) findViewById(R.id.myLayout);
        layout.addSoftKeyboardLsner(new SoftKeyboardLsner() {
            @Override
            public void onSoftKeyboardShow() {
                Log.d("SoftKeyboard", "Soft keyboard shown");
            }

            @Override
            public void onSoftKeyboardHide() {
                Log.d("SoftKeyboard", "Soft keyboard hidden");
            }
        });
    }
}
Lolme
  • 21
  • 1
1

try these methods: showSoftInput(View, int, ResultReceiver) and hideSoftInputFromWindow(IBinder, int, ResultReceiver). You can override onReceiveResult(int resultCode, Bundle resultData) method of ResultReceiver class to handle show/hide event.

George Powell
  • 7,511
  • 8
  • 30
  • 43
  • This way you'll only receive a callback when your requested action has been done. But not when any future events happen. It would be nice if we receive the user's hide events (e.g. back button) when handed a `ResultReceiver` to `showSoftInput`, but that's not the case. – TWiStErRob Apr 23 '15 at 11:45
0

Many of Android developer like to alter the layout based on whether the virtual keyboard is shown or not.so for solution you can see Android: Detect softkeyboard open.and it is working for me and i think it is so usefull as well.

Community
  • 1
  • 1
John smith
  • 1,671
  • 14
  • 27
-6

You can capture this by overwriting the onConfigurationChanged method of your activity:

@Override
public void onConfigurationChanged(Configuration newConfig) {
   super.onConfigurationChanged(newConfig);

   if(newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
      ((SherlockFragmentActivity)getActivity()).getSupportActionBar().hide();
   }
   else if(newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES){
      ((SherlockFragmentActivity)getActivity()).getSupportActionBar().show();
   }
}
Michael Yaworski
  • 12,398
  • 17
  • 59
  • 91
ePeace
  • 1,919
  • 1
  • 16
  • 23