I made a custom keyboard. When you long press a key, a PopupWindow
shows some extra choices above the key. The problem is that in API 28, this popup gets clipped (or even completely hidden for the top row).
I had solved this problem for API < 28 with
popupWindow.setClippingEnabled(false);
However, with API 28 the problem has come back. Here is more of the code:
private void layoutAndShowPopupWindow(Key key, int xPosition) {
popupWindow = new PopupWindow(popupView,
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
popupWindow.setClippingEnabled(false);
int location[] = new int[2];
key.getLocationInWindow(location);
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
popupView.measure(measureSpec, measureSpec);
int popupWidth = popupView.getMeasuredWidth();
int spaceAboveKey = key.getHeight() / 4;
int x = xPosition - popupWidth / popupView.getChildCount() / 2;
int screenWidth = getScreenWidth();
if (x < 0) {
x = 0;
} else if (x + popupWidth > screenWidth) {
x = screenWidth - popupWidth;
}
int y = location[1] - popupView.getMeasuredHeight() - spaceAboveKey;
popupWindow.showAtLocation(key, Gravity.NO_GRAVITY, x, y);
}
Did something happen to no longer allow third party keyboards to show content outside of the keyboard view? (This is how it is in iOS.)
What do I need to do to get the PopupWindow
to stop being clipped?
Updated to show a more tailored approach.
Updated to work with
windowSoftInputMode="adjustResize"
.It looks like clipping outside of windows may be a new fact of Android life although I have not found documentation to that effect. Regardless, the following method may be the preferred way to go and is, I believe, standard although not very well documented.
In the following,
MyInputMethodService
instantiates a keyboard that has eight keys on the bottom and an empty view strip above where popups are displayed for the top row of keys. When a key is pressed, the key value is shown in a popup window above the key for the duration of the key press. Since the empty view above the keys encloses the popups, clipping does not occur. (Not a very useful keyboard, but it makes the point.)The button and "Low text"
EditText
are under the top view strip. Invocation ofonComputeInsets()
permits touches on the keyboard keys but disallows keyboard touches in the empty area covered by the inset. In this area, touches are passed down to the underlying views - here the "Low text"EditText
and aButton
that displays "OK!" when clicked."Gboard" seems to work in a similar fashion but uses a sister
FrameLayout
to display the popups with translation. Here is what a "4" popup looks like in the Layout Inspector for "Gboard".MyInputMethodService
keyboard.xml
The
View
is defined solely to give the popups a place to expand into and has no other purpose.popup.xml
Just the popup.
activity_main
A general idea to show popup views is to create them using
WindowManager
which has not limitations ofPopupWindow
.I assume that the
InputMethodService
is responsible to show the popup view. As showing such window needs to get overlay permission in API 23 and higher, we need to make a tempActivity
to do this for us . The result of getting permission would be delivered to theInputMethodService
using anEventBus
event. You can check the overlay permission where you want according to architecture (for example every time the keyboard goes up).Here is an implementation of this idea which may need some manipulations to work exactly you want. I hope it helps.
MyInputMethodService.java
FloatViewManager.java
CheckPermissionActivity.java
CanDrawOverlaysEvent.java
build.gradle
I have fixed that with LatinIME(AOSP) like: