我想为Android制作一个曲面屏幕键盘。我已经检查了softkeyboard和谷歌代码中的各种其他屏幕键盘。我没有找到任何形状不是矩形的键盘。理想情况下,我想创建一个键盘,由分布在屏幕两个半圆上相对位置的按键组成(例如,想象一下通过侧边握住平板电脑,并能用拇指击打按键)。
在我检查的代码中,屏幕键盘被创建为视图(通常扩展KeyboardView),并显示为跨越屏幕底部的连续条。为了达到我的目标,我尝试修改我在谷歌代码(dotdash-keyboard-android)中找到的代码,只在左下角绘制其键,并使右下角透明。我已经能够覆盖onMeasure以影响视图的尺寸(请参见下文),但这似乎只改变了键的位置而不是容器的位置。换句话说,仍然有一个黑色的条填充着屏幕底部。
我想做的事情有可能吗?这个术语是否更加准确?有没有可以用作示例的项目?
我也尝试使用this.setLayoutParams设置视图的尺寸,但是这些调用似乎没有效果。我还尝试使用this.getParent来访问父视图(如果存在),并更改其尺寸,但是这种方法不起作用(或者,我只是做错了)。非常感谢任何帮助。
谢谢
更新:12/21/2012 - 我认为我需要覆盖父类的onDraw方法。在这里查看,看起来KeyboardView的onDraw方法使用以下代码绘制大小等于屏幕大小的画布:
源代码。以下方法位于服务IME类中,并由子视图(服务的子项)的onMeasure方法调用,以便在绘制键盘时同时打开弹出窗口。我将键盘的尺寸设置为1x1,因此它不可见。日志语句是为了帮助我确定如何定位弹出窗口。
在我检查的代码中,屏幕键盘被创建为视图(通常扩展KeyboardView),并显示为跨越屏幕底部的连续条。为了达到我的目标,我尝试修改我在谷歌代码(dotdash-keyboard-android)中找到的代码,只在左下角绘制其键,并使右下角透明。我已经能够覆盖onMeasure以影响视图的尺寸(请参见下文),但这似乎只改变了键的位置而不是容器的位置。换句话说,仍然有一个黑色的条填充着屏幕底部。
//Located within KeyboardView
@Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
this.setMeasuredDimension(200, 200);
}
我想做的事情有可能吗?这个术语是否更加准确?有没有可以用作示例的项目?
我也尝试使用this.setLayoutParams设置视图的尺寸,但是这些调用似乎没有效果。我还尝试使用this.getParent来访问父视图(如果存在),并更改其尺寸,但是这种方法不起作用(或者,我只是做错了)。非常感谢任何帮助。
谢谢
更新:12/21/2012 - 我认为我需要覆盖父类的onDraw方法。在这里查看,看起来KeyboardView的onDraw方法使用以下代码绘制大小等于屏幕大小的画布:
final int width = Math.max(1, getWidth());
final int height = Math.max(1, getHeight());
mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBuffer);
我认为我可以重写onDraw并在画布上绘制任何我想要的内容。
更新:2012年12月21日 - 我已经重写了onDraw,现在清楚地看到keyboardView是我设置的尺寸(200x200)。使用Hierarchyview,我可以看到keyboardview在id为InputArea的framelayout内。因此,填充整个宽度的水平条是这个framelayout。但是,我没有创建它-它从哪里来,如何改变其尺寸?
更新:2012年12月22日 - 经过更多测试,似乎键盘视图的行为(尺寸)在某种程度上取决于调用它的活动。在浏览器中,我得到了我描述的行为:浏览器窗口的高度会缩小以适应屏幕底部的一个条形区域,该区域包含键盘,即使键盘的宽度小于屏幕的宽度。在日历应用程序中,键盘大小显示为我设置的样子(在左下角的正方形),而日历在其下方不变。因此,使用这种方法似乎不可能达到我的目标。另一种方法可能是让IME服务创建一个弹出窗口或对话框。一个问题是popupwindows需要一个父视图或锚点来附加,我不认为从IME服务中可以找到最顶层的视图。也许我可以在当前活动上创建一个透明视图,并将弹出窗口放在其上方?
更新:2012年12月23日——进展。我已经找到了如何从键盘IME显示弹出窗口的方法。下一步是弄清楚如何使弹出窗口更加圆润/有机。以下是我完成的截图和源代码。![Emulator screenshot of keyboard](https://istack.dev59.com/PvCKY.webp)
public void initiatePopupWindow()
{
try {
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
display.getMetrics(dm);
//display.getSize(p);
Log.i("dotdashkeyboard","initiatePopupWindow (from IME service)");
LayoutInflater inflater = (LayoutInflater) this.getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layoutLeft = inflater.inflate(R.layout.popup_layout_left,null);
View layoutRight = inflater.inflate(R.layout.popup_layout_right, null);
// create a 300px width and 470px height PopupWindow
int popupHeight = 300;
int popupWidth = 200;
if (popUpLeft == null) popUpLeft = new PopupWindow(layoutLeft, popupWidth, popupHeight, false);
if (popUpRight == null) popUpRight = new PopupWindow(layoutRight, popupWidth, popupHeight, false);
int ypos = 0;
int xposRight = 0;
if (display.getRotation() == Surface.ROTATION_0) {
ypos = -(dm.heightPixels / 2 + popupHeight/2);
xposRight = (dm.widthPixels - popupWidth);
Log.i("dotdashkeyboard","test rotation=normal");
} else if (display.getRotation() == Surface.ROTATION_90) {
ypos = -(dm.heightPixels / 2 + popupHeight/2)/2;
xposRight = (dm.widthPixels - popupWidth)*2-popupWidth;
Log.i("dotdashkeyboard","test rotation=90-degrees");
} else {
Log.i("dotdashkeyboard","test rotation=unknown=" + display.getRotation());
}
popUpLeft.showAtLocation(inputView, Gravity.NO_GRAVITY, 0, ypos);
popUpRight.showAtLocation(inputView, Gravity.NO_GRAVITY, xposRight, ypos);
Log.i("dotdashkeyboard","test created popup at ypos="+ypos + " xposRight=" + xposRight);
Log.i("dotdashkeyboard","test screenWidth=" + dm.widthPixels + " screenHeight=" + dm.heightPixels);
Button cancelButton = (Button) layoutLeft.findViewById(R.id.popup_cancel_button);
//cancelButton.setOnClickListener(inputView.cancel_button_click_listener);
cancelButton.setOnClickListener(cancel_button_click_listener);
} catch (Exception e) {
e.printStackTrace();
}
}