如何为Android制作一个曲面屏键盘

31
我想为Android制作一个曲面屏幕键盘。我已经检查了softkeyboard和谷歌代码中的各种其他屏幕键盘。我没有找到任何形状不是矩形的键盘。理想情况下,我想创建一个键盘,由分布在屏幕两个半圆上相对位置的按键组成(例如,想象一下通过侧边握住平板电脑,并能用拇指击打按键)。
在我检查的代码中,屏幕键盘被创建为视图(通常扩展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 源代码。以下方法位于服务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();
    }
}

2
使用弯曲的形状,查看这个链接:http://stackoverflow.com/a/10140513/793943。 - Sush
1
有趣的问题 - 我会关注可能的答案...不幸的是,我没有什么可以帮助你的。 - Richard Le Mesurier
1个回答

1
你似乎在这方面走在了正确的轨道上。正如你已经注意到的那样,大多数活动都会缩小它们的视图以为键盘窗口提供空间,因此如果你想要调用活动填满屏幕,你需要使用一个辅助窗口,比如 PopupWindow。你可以将主窗口的尺寸设置为0x0。
你是否尝试过调用 popUpLeft.setBackgroundDrawable(null) / popUpRight.setBackgroundDrawable(null)?这应该去掉半透明背景,并仅显示你在顶部绘制的内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接