ban*_*ing 10 android android-layout android-custom-keyboard
我创建了一个自定义键盘,它工作正常 - 除了前两行键的预览视图显示不够高.它们的垂直位置受到父布局的约束.
这些屏幕截图说明了问题 - "0"和"8"的预览位置是好的,但对于"5"和"2",它不是:
键'0'的预览显示在按钮上方...
键'8'的预览也显示在按钮上方...
但键'5'的预览未显示在按钮上方...
键'2'的预览未显示在按钮上方...
如何克服,因此"5"和"2"的预览显示在它们各自键上方相同的距离处,与"0"和"8"相同.
这是我的keyboard.xml ...
<android.inputmethodservice.KeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keyboard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:keyPreviewLayout="@layout/keyboard_key_preview" />
Run Code Online (Sandbox Code Playgroud)
这是我的keyboard_key_preview.xml ...
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@color/keyboard_preview_bg"
android:textColor="@color/keyboard_preview_fg"
android:textStyle="bold"
android:textSize="@dimen/keyboard_preview_text_size" />
Run Code Online (Sandbox Code Playgroud)
这是我的keyboard_numeric.xml布局......
<Keyboard
xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="33.33%p"
android:keyHeight="@dimen/keyboard_key_height"
android:horizontalGap="@dimen/keyboard_horizontal_gap"
android:verticalGap="@dimen/keyboard_vertical_gap">
<Row android:rowEdgeFlags="top">
<Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
<Key android:codes="50" android:keyLabel="2"/>
<Key android:codes="51" android:keyLabel="3" android:keyEdgeFlags="right"/>
</Row>
<Row>
<Key android:codes="52" android:keyLabel="4" android:keyEdgeFlags="left"/>
<Key android:codes="53" android:keyLabel="5"/>
<Key android:codes="54" android:keyLabel="6" android:keyEdgeFlags="right"/>
</Row>
<Row>
<Key android:codes="55" android:keyLabel="7" android:keyEdgeFlags="left"/>
<Key android:codes="56" android:keyLabel="8"/>
<Key android:codes="57" android:keyLabel="9" android:keyEdgeFlags="right"/>
</Row>
<Row android:rowEdgeFlags="bottom">
<Key android:codes="-5" android:keyIcon="@drawable/ic_backspace_white_24dp" android:isRepeatable="true" android:keyEdgeFlags="left" />
<Key android:codes="48" android:keyLabel="0"/>
<Key android:codes="-4" android:keyLabel="DONE" android:keyEdgeFlags="right"/>
</Row>
</Keyboard>
Run Code Online (Sandbox Code Playgroud)
预览键实际上是PopupWindow
在构造函数中创建的KeyboardView
.(见这里的代码).
您遇到的问题是因为PopupWindow
其父级正在剪切它.如果可以禁用剪辑,PopupWindow
那么预览键将能够在键盘视图之外"弹出".如果在上面引用的代码中设置断点并执行以下代码,则可以看到此方法有效:
mPreviewPopup.setClippingEnabled(false)
Run Code Online (Sandbox Code Playgroud)
请参阅文档中的setClippingEnabledPopupWindow
.默认情况下,启用剪裁.
setClippingEnabled
void setClippingEnabled(已启用布尔值)
允许弹出窗口超出屏幕范围.默认情况下,窗口被剪切到屏幕边界.将此设置为false将允许窗口准确定位.
它显示"屏幕",但它也适用于键盘窗口.
剩下的问题是:如何禁用剪辑?不幸的是,它mPreviewPopup
是一个私有变量.反思将提供访问但不理想.我还没有找到另一种方法来禁用此私有的剪辑PopupWindow
,所以这只是指向分辨率而不是分辨率本身.
更新:我再看看发生了什么.以下是我在各种API级别中发现的内容.
API 17-21:允许键盘预览弹出键盘边界.
API 22,23,25-26:键预览受限于键盘的边界,但确实完整显示.这就是OP所看到的.
API 24:键预览被约束到键盘的边界,但是被剪裁.(破碎)
因此,API 22发生了变化.我在API 21和API 22之间看到的唯一实质性差异是支持FLAG_LAYOUT_ATTACHED_IN_DECOR标志.(另请参阅setAttachedInDecor.)此代码确实处理弹出窗口的位置,因此可能与此问题有关.(我不再相信这是真的.)
我也发现这也可能是相关的.(也许...)
setClippingEnabled()
适用于API 22-26,允许预览键弹出键盘布局的边界.除了使用反射,我没有找到纠正问题的方法.
虽然新的约束行为可能是预期的行为,但这可能有资格获得错误报告.
下面是API 26的出现该问题的视频,然后我设置mClippingEnabled
到标志false
中PopupWindow.java
,并显示修正行为.
对于将来来这里的人,我建议不要使用KeyboardView
. 至少在撰写本文时(API 27),它已经很长时间没有更新了。上述问题所描述的问题只是其众多缺点之一。
这需要更多工作,但您可以制作自己的自定义视图来用作键盘。我在这个答案的末尾描述了这个过程。
当您在自定义键盘中创建弹出预览窗口时,您需要调用popupWindow.setClippingEnabled(false)
以使弹出窗口显示在 Android API 22+ 的键盘上方。(感谢这个答案的见解。)
这是我最近的一个项目中的一个例子。
private void layoutAndShowPopupWindow(Key key, int xPosition) {
popupWindow = new PopupWindow(popupView,
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
popupWindow.setClippingEnabled(false);// <-- let popup display above keyboard
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 y = location[1] - popupView.getMeasuredHeight() - spaceAboveKey;
popupWindow.showAtLocation(key, Gravity.NO_GRAVITY, x, y);
// using popupWindow.showAsDropDown(key, 0, yOffset) might be
// easier than popupWindow.showAtLocation()
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2281 次 |
最近记录: |