3

I have not yet found any way to solve this on stack.

I have a webview in my app. I want to be able to detect when the keyboard is active and when it is not active. It seems as if it cant detect these changes when they happon in a webview.

I want to perform actions on these different states. On iOS its really simple with observers that listens when the keyboard is active. Ref UIKeyboardWillShow/Hide.

Is there any functionality in android that does the same as these observers do in android?

Hopefully the question is well enough explained.

Phantômaxx
  • 36,442
  • 21
  • 78
  • 108
  • Possible duplicate of [SoftKeyboard open and close listener in an activity in Android?](https://stackoverflow.com/questions/25216749/softkeyboard-open-and-close-listener-in-an-activity-in-android) – SripadRaj Mar 05 '18 at 12:30
  • Dont think so. Those answers seems to include native built in "EditText" and I have a webview with textfields. I need to know when these fields are active or not. Thats simple on ios, but there seems to be more to it on Android. – The Normal One Mar 05 '18 at 12:49
  • why not? I assume your web view has text fields which will by default open the keyboard. You could attach a listener to the webview. You can try and I think it should work. – SripadRaj Mar 05 '18 at 12:57

1 Answers1

0

So I struggled with this a week or so and found a lot of material Here is my solution, I really hope that it works for you.

So in my case I have an Activity, and I call a fragment that contains the Webview so it was a lot trickier than I thought.

Basically the issue is that the fragment was missing this line:

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

So it didn't recognized the change of height inside the webview.

Anyways lets get to the code:

@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 and retrieve from there using getResources().getInteger() 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);
}

Remember to put on your AndroidManifest.xml a setting on the activity set to: android:windowSoftInputMode="adjustResize|stateHidden"

The variables inside the fragment are:

public boolean isSoftKeyboardPresent = false;
private int previousHeightDiff = -1;// this is used to avoid multiple assignments
private ViewTreeObserver.OnGlobalLayoutListener layoutListener = null;

Finally

@Override
public void onPause() {
    super.onPause();
    final View activityRootView = getActivity().findViewById(R.id.page_content);
    activityRootView.getViewTreeObserver().removeOnGlobalLayoutListener(layoutListener);
}

And this should do the trick :) so what do you think?