我做了一个自定义键盘。长按一个键时,PopupWindow
将在该键上方显示一些其他选择。问题在于,在API 28中,此弹出窗口会被裁剪(甚至在第一行中完全隐藏)。
I had solved this problem for API < 28与
popupWindow.setClippingEnabled(false);
但是,有了API 28,问题又回来了。这里是更多的代码:
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);
}
第三方键盘无法再显示超出键盘 View 范围的内容吗? (这就是iOS中的情况。)
我需要怎么做才能使
PopupWindow
不再被剪切? 最佳答案
更新以显示更定制的方法。更新以与windowSoftInputMode="adjustResize"
一起使用。
似乎在Windows外部进行剪切可能是Android生活中的一个新事实,尽管我还没有找到达到这种效果的文档。无论如何,以下方法可能是首选的方法,并且我认为它是标准的方法,尽管没有得到很好的记录。
在下面的代码中,MyInputMethodService
实例化了一个键盘,该键盘的底部有八个键,上方有一个空白的 View 条,在该 View 条的上一行显示弹出窗口。按下某个键时,在按键持续时间内,该键值将显示在该键上方的弹出窗口中。由于键上方的空 View 将弹出窗口包围起来,因此不会发生剪切。 (这不是一个非常有用的键盘,但很重要。)
该按钮和“Low text” EditText
在顶 View 条下方。 onComputeInsets()
的调用允许在键盘按键上进行触摸,但不允许在插图所覆盖的空白区域进行键盘触摸。在该区域中,触摸向下传递到基础 View -这里是“低文本” EditText
和显示“OK!”的Button
。单击时。
“Gboard”似乎以类似的方式工作,但是使用姐妹FrameLayout
来显示带有翻译的弹出窗口。这是“Gboard”的布局检查器中的“4”弹出窗口。
MyInputMethodService
public class MyInputMethodService extends InputMethodService
implements View.OnTouchListener {
private View mTopKey;
private PopupWindow mPopupWindow;
private View mPopupView;
@Override
public View onCreateInputView() {
final ConstraintLayout keyboardView = (ConstraintLayout) getLayoutInflater().inflate(R.layout.keyboard, null);
mTopKey = keyboardView.findViewById(R.id.a);
mTopKey.setOnTouchListener(this);
keyboardView.findViewById(R.id.b).setOnTouchListener(this);
keyboardView.findViewById(R.id.c).setOnTouchListener(this);
keyboardView.findViewById(R.id.d).setOnTouchListener(this);
keyboardView.findViewById(R.id.e).setOnTouchListener(this);
keyboardView.findViewById(R.id.f).setOnTouchListener(this);
keyboardView.findViewById(R.id.g).setOnTouchListener(this);
keyboardView.findViewById(R.id.h).setOnTouchListener(this);
mPopupView = getLayoutInflater().inflate(R.layout.popup, keyboardView, false);
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
mPopupView.measure(measureSpec, measureSpec);
mPopupWindow = new PopupWindow(mPopupView, ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
return keyboardView;
}
@Override
public void onComputeInsets(InputMethodService.Insets outInsets) {
// Do the standard stuff.
super.onComputeInsets(outInsets);
// Only the keyboard are with the keys is touchable. The rest should pass touches
// through to the views behind. contentTopInsets set to play nice with windowSoftInputMode
// defined in the manifest.
outInsets.visibleTopInsets = mTopKey.getTop();
outInsets.contentTopInsets = mTopKey.getTop();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
layoutAndShowPopupWindow((TextView) v);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mPopupWindow.dismiss();
break;
}
return true;
}
private void layoutAndShowPopupWindow(TextView key) {
((TextView) mPopupView.findViewById(R.id.popupKey)).setText(key.getText());
int x = key.getLeft() + (key.getWidth() - mPopupView.getMeasuredWidth()) / 2;
int y = key.getTop() - mPopupView.getMeasuredHeight();
mPopupWindow.showAtLocation(key, Gravity.NO_GRAVITY, x, y);
}
}
keyboard.xml
View
的定义仅是为弹出窗口提供扩展的空间,没有其他目的。<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/a" />
<Button
android:id="@+id/a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="A"
app:layout_constraintBottom_toTopOf="@+id/e"
app:layout_constraintEnd_toStartOf="@+id/b"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="B"
app:layout_constraintBottom_toTopOf="@+id/f"
app:layout_constraintEnd_toStartOf="@+id/c"
app:layout_constraintStart_toEndOf="@+id/a" />
<Button
android:id="@+id/c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="C"
app:layout_constraintBottom_toTopOf="@+id/g"
app:layout_constraintEnd_toStartOf="@+id/d"
app:layout_constraintStart_toEndOf="@+id/b" />
<Button
android:id="@+id/d"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="D"
app:layout_constraintBottom_toTopOf="@+id/h"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/c" />
<Button
android:id="@+id/e"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="E"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/f"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/f"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="F"
app:layout_constraintEnd_toStartOf="@+id/g"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/e"
app:layout_constraintTop_toTopOf="@+id/e" />
<Button
android:id="@+id/g"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="G"
app:layout_constraintEnd_toStartOf="@+id/h"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/f"
app:layout_constraintTop_toTopOf="@+id/e" />
<Button
android:id="@+id/h"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="H"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/g"
app:layout_constraintTop_toTopOf="@+id/g" />
</android.support.constraint.ConstraintLayout>
popup.xml
只是弹出窗口。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:background="@android:color/black"
android:gravity="center"
android:orientation="vertical"
android:padding="3dp">
<TextView
android:id="@+id/popupKey"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:text="A"
android:textColor="@android:color/white" />
</LinearLayout>
activity_main
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="High text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="20dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<EditText
android:id="@+id/editText"
android:layout_width="133dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:ems="10"
android:inputType="textPersonName"
android:hint="Low text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/button" />
</android.support.constraint.ConstraintLayout>