如何为Android制作弯曲的屏幕键盘

时间:2012-12-21 04:43:23

标签: android keyboard

我想为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方法。看here,看起来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并在画布上绘制我想要的任何内容。

更新:12/21/2012 - 我已经覆盖了onDraw,现在很清楚,keyboardView是我将其设置为(200x200)的尺寸。使用Hierarchyview,我可以看到键盘视图位于具有id InputArea的framelayout中。因此,填充整个宽度的水平条是此framelayout。但是,我不是在创造它 - 它来自何处以及如何改变其尺寸?

更新:12/22/2012 - 经过更多测试后,看起来键盘视图的行为(维度)部分取决于调用它的活动。在浏览器中,我得到了我一直在描述的行为:浏览器窗口的高度缩小以适应屏幕底部的一个条形,即使键盘的宽度小于键盘的宽度屏幕。在日历应用程序中,键盘大小显示为我设置的(左下角为正方形),日历下方的日历显示不变。因此,使用此方法的大多数应用程序似乎无法实现我的目标。另一种方法可能是让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();
    }
}

1 个答案:

答案 0 :(得分:1)

你似乎走在正确的轨道上。正如您所指出的,大多数活动都会缩小视图以为键盘窗口提供空间,因此如果您希望调用活动填满屏幕,则需要使用辅助窗口,例如PopupWindow。您可以将主窗口的尺寸设置为0x0。

您是否尝试过调用popUpLeft.setBackgroundDrawable(null) / popUpRight.setBackgroundDrawable(null)?这应该删除半透明背景并仅显示您在顶部绘制的任何内容。