我想为 Android 制作一个弯曲的屏幕键盘。我检查了软键盘,以及谷歌代码上的各种其他屏幕键盘。我发现没有一个键盘形状不是矩形。理想情况下,我想创建一个键盘,该键盘由分布在屏幕两侧的两个半圆上的键组成(即,想象一下将平板电脑放在两侧并能够用拇指敲击键)。
在我检查过的代码中,屏幕键盘被创建为视图(通常扩展 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,我可以看到键盘视图位于 ID 为 InputArea 的框架布局内。所以,填满整个宽度的单杠就是这个framelayout。但是,我不是在创造它——它来自哪里,我怎样才能改变它的尺寸?
更新:2012 年 12 月 22 日 - 经过更多测试后,似乎键盘视图的行为(尺寸)部分取决于调用它的活动。在浏览器中,我得到了我一直在描述的行为:即使键盘的宽度小于屏幕。在日历应用程序中,键盘大小显示为我设置的大小(作为左下角的正方形),日历在其下方显示不变。因此,使用这种方法的大多数应用程序似乎不可能达到我的目标。另一种方法可能是让 IME 服务创建一个弹出窗口或对话框。一个问题是popupwindows需要一个父视图或锚点来附加,我不认为它' 可以从 IME 服务中找到最顶层的视图。也许我可以在当前活动上创建一个透明视图并将弹出窗口放在上面?
更新:2012 年 12 月 23 日 - 进展。我已经弄清楚如何从键盘 IME 显示弹出窗口。下一步是弄清楚如何使弹出窗口有点圆/有机。这是我完成的屏幕截图,然后是源代码。
资源。以下方法在服务 IME 类中,由子(服务)视图的 onMeasure 方法调用,以便在绘制键盘的同时打开弹出窗口。我已将键盘的尺寸设置为 1x1,因此它不可见。日志语句可以帮助我弄清楚如何定位弹出窗口。
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();
}
}