Android: how can i tell if the soft keyboard is showing or not?-ThrowExceptions

Exception or error:

Heres the dilemma:
I am showing a screen with 3 input fields and 2 buttons inside of a tab(there are 3 tabs total, and they are on the bottom of the screen). the 2 buttons are set to the bottom left and right of the screen, right above the tabs. when i click on an input field, the tabs and buttons are all pushed up on top of the keyboard.

i desire to only push the buttons up, and leave the tabs where they originally are, on the bottom. i am thinking of setting the visibility of the tabs to GONE once i determine that the soft keyboard is showing, and visibility to VISIBLE once the soft keyboard is gone.

is there some kind of listener for the soft keyboard, or maybe the input field? maybe some tricky use of OnFocusChangeListener for the edit text? How can i determine whether the keyboard is visible or not?

How to solve:

Determining if the keyboard is showing is not possible apparently.

You might want to disable it alltogether with the windowSoftInputMode xml tag in your manifest: http://developer.android.com/reference/android/R.attr.html#windowSoftInputMode. Or you can have a look on how to remove focus to hide the keyboard: Hide soft keyboard on activity without any keyboard operations.

Neither will exactly solve your problem. I remember reading a blogpost strongly advising not to use tabs at the bottom, rather than the top of the screen, for UI clarity reasons. I recommend you to follow up on that.

###

As far as I know, you can’t.

However, you can monitor size changes of your layout, and since keyboard showing up is the main cause for the resizes, you might be able to assume that the keyboard is shown or not.

Here’s a sample code for monitoring the size-changes of a layout. Just use this layout as the parent of your original layout, and use its listener. If the height has decreased, you can assume the keyboard is shown, and if it was increased, you can assume it got closed.

public class LayoutSizeChangedSensorFrameLayout extends FrameLayout {
    public enum SizeChange {
        HEIGHT_INCREASED, HEIGHT_DECREASED, WIDTH_INCREASED, WIDTH_DECREASED
    }

    public interface OnLayoutSizeChangedListener {
        void onSizeChanged(EnumSet<SizeChange> direction);
    }

    private OnLayoutSizeChangedListener mLayoutSizeChangeListener;

    public LayoutSizeChangedSensorFrameLayout(final Context context) {
        super(context);
    }

    public LayoutSizeChangedSensorFrameLayout(final Context context, final AttributeSet attributeSet) {
        super(context, attributeSet);
    }

    public LayoutSizeChangedSensorFrameLayout(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);
    }

  @Override
  protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
      super.onSizeChanged(w, h, oldw, oldh);
      if (mLayoutSizeChangeListener != null) {
          final EnumSet<SizeChange> result = EnumSet.noneOf(SizeChange.class);
          if (oldh > h)
              result.add(SizeChange.HEIGHT_DECREASED);
          else if (oldh < h)
              result.add(SizeChange.HEIGHT_INCREASED);
          if (oldw > w)
              result.add(SizeChange.WIDTH_DECREASED);
          else if (oldw < w)
              result.add(SizeChange.WIDTH_INCREASED);
          if (!result.isEmpty())
              mLayoutSizeChangeListener.onSizeChanged(result);
      }
  }

    public void setOnLayoutSizeChangedListener(final OnLayoutSizeChangedListener layoutSizeChangeListener) {
        this.mLayoutSizeChangeListener = layoutSizeChangeListener;
    }

    public OnLayoutSizeChangedListener getOnLayoutSizeChangeListener() {
        return mLayoutSizeChangeListener;
    }
}

###

This might help
http://developer.android.com/reference/android/inputmethodservice/InputMethodService.html

https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+/master/java/src/com/android/inputmethod/latin

The keyboard code is here, I grepped through it a little but give up, I don’t see any Broadcasts being sent that would be of any use, at least in here. Maybe you can go find lower level code in the repo and find a useful Intent being sent. The first linke might tell you when it becomes visible, but I’m not sure how to tell when it becomes invisible.

###

Working solution for me –

ViewTreeObserver treeObserver = getViewTreeObserver();
        if (treeObserver != null)
            treeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    int pHeight = getResources().getDisplayMetrics().heightPixels;

                Rect visRect = new Rect();
                viewGroup.getWindowVisibleDisplayFrame(visRect);

                boolean keyboardVisible;
                int keyboardHeight= pHeight-currentHeight;
                if (keyboardHeight > (MIN_KEYBOARD_HEIGHT*pHeight))
                {
                    TGVLog.d(debugTag, "keyboardVisible-- "+true);
                    keyboardVisible = true;
                }
                else
                {
                    TGVLog.d(debugTag, "keyboardVisible-- "+false);
                    keyboardVisible = false;
                }
                }
            });

###

In my last application I had some issues in displaying the soft keyboard, then I have used the following code in my Manifest file:

<activity
android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation"
android:name=".rate.Calculator"/>

Leave a Reply

Your email address will not be published. Required fields are marked *