创建每个键具有多个/备用字符的SoftKeyboard

Gra*_*eme 44 android soft-keyboard android-softkeyboard

我已经关注了developer.android.com上有关 输入法的示例,并使用了SoftKeyboard示例应用程序.这些共同提供了有关简单键盘创建的足够信息.

我在API中看不到的是能够在标准键盘(LatinIME键盘)上为每个键创建备用/多个字符.

在此输入图像描述

上面的图像是长按"a"键的结果.当您长按一个键时,可以使用替换字符填充弹出窗口.

在此输入图像描述

也可以在某些键上给出一个弹出提示,提示用户按住一个键以获得弹出菜单.

到目前为止,我还没有找到关于如何实现这一目标的单一信息来源,希望有人能够给我一个良好的开端,直到那时我将遵循内置键盘的源代码,看看我是否可以进行逆向工程它.

编辑:如果developer.android.com的LatinIME键盘链接没有链接到一个的图片会有帮助:) LatinIME.java的实际源代码.

编辑2:更多作为参考而不是其他任何东西,这是我认为通常的longPress操作通过以便在KeyboardView.java中显示弹出键盘的序列:

onTouchEvent()
onModifiedTouchEvent()
mHandkler.handleMessage() with MSG_LONGPRESS
openPopupIfRequired() 
onLongPress()
Run Code Online (Sandbox Code Playgroud)

编辑3:

我仍然没有想到这一点 - 如何向键添加标签建议?答案表明它没有内置到API中,事实上我还没有找到代码来执行此操作.但是,2.3.4(API 10)上的键盘显示正在实现此功能:

在此输入图像描述

非常想弄清楚IT是如何做到的,但它不是onDraw()我能看到的方法中的任何地方- 这让我相信它是在KeyboardView元素之外编写的.然而,我无法找到layout用于在内置键盘上显示KeyboardView元素的文件 - 如果有人知道在哪里找到这个也许会给我提供我需要的线索.

编辑4:移动键预览问题,因为它稍微偏离主题:

如何禁用SoftKeyboard键预览窗口?

Gra*_*eme 51

实现备用密钥弹出窗口:

对于您希望拥有弹出键盘的每个键,您应该定义popupCharacterspopupKeyboard:

/res/xml/[Keyboard].xml

<Key android:keyLabel="("
    android:popupKeyboard="@xml/keyboard_popup_template"
    android:popupCharacters="[{&lt;" />
Run Code Online (Sandbox Code Playgroud)

popupKeyboard是包含备用键的弹出窗口中使用的键盘的XML表示形式:

/res/xml/keyboard_popup_template.xml

<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="10%p"
    android:horizontalGap="0px"
    android:verticalGap="0px"
    android:keyHeight="56dp">
</Keyboard>
Run Code Online (Sandbox Code Playgroud)

样式化备用键弹出窗口:

如果要更改弹出窗口的布局/样式(默认为@android:layout/keyboard_popup_keyboard.xml),可以指定一个android:popupLayout指向布局文件的属性:

<android.inputmethodservice.KeyboardView
    android:id="@+id/keyboard"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="#FF272727"
    android:popupLayout="@layout/keyboard_popup_keyboard" />
Run Code Online (Sandbox Code Playgroud)

实现密钥预览叠加:

我能够联合起来展示关键预览(没有完全重写KeyboardView源代码)的唯一解决方案如下:

<KeyboardView>使用<FrameLayout>keyHeight乘以行数指定的高度来包装标记.在这个标签里面,我只创建了一个LinearLayout来保存行,然后为包含TextView的每一行创建一个LinearLayout,其权重等于为每个行指定的%p值<Key>:

<TextView android:text="!" style="@style/Custom.Widget.KeyboardKeyOverlay"  android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="10"/>
Run Code Online (Sandbox Code Playgroud)

风格:

<style name="CustomTheme.Widget.KeyboardKeyOverlay">
    <item name="android:background">@android:color/transparent</item>
    <item name="android:textColor">#FFAAAAAA</item>
    <item name="android:paddingRight">6dp</item>
    <item name="android:paddingTop">4dp</item>
    <item name="android:textSize">10sp</item>
    <item name="android:gravity">right</item>
    <item name="android:textStyle">bold</item>
</style>         
Run Code Online (Sandbox Code Playgroud)

产生这个:

在此输入图像描述

在我设法以与系统键盘相同的方式实现此功能之前,我不会高兴!


Lau*_*nt' 14

从我自己尝试编写软键盘开始,我发现:

  • Nice/bling功能通常要求您扩展KeyboardView并基本上编写绘图代码的大部分内容.不幸的是,你不能通过覆盖一些关键方法做到这一点,因为几乎所有东西都是私有的 你可能想看看(并从中借用一些代码:
    • (base)/core/java/android/inputmethodservice/KeyboardView.java (android核心代码回购)
    • (apps)/other/LatinIME/LatinKeyboardView.java (android核心应用程序回购)

请注意,android.kernel.org上的绵羊会告诉你由于破解程序而关闭了回购,但是在其他地方有代码镜像(遗憾的是丢失了链接)

  • 该基地KeyboardView没有对阴影重点提示的支持,您必须编写自己的KeyboardView获得机会重写的onDraw()方法.

现在你可以做什么:

  • 您可以通过为密钥提供图片来解决此问题:使用xml <Key ... android:keyIcon="@drawable/this_key_icon_file />进行此操作.不幸的是,对于使用此方法的字母,您肯定会得到较差的结果(分辨率问题).

  • 您可以使用长按时出现的弹出键盘(并配置其外观).

声明键盘模板res/xml/kbd_popup_template.xml:

<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="10%p"
    android:horizontalGap="0px"
    android:verticalGap="0px"
    android:keyHeight="@dimen/key_height">
</Keyboard>
Run Code Online (Sandbox Code Playgroud)

声明包含此键盘上所需键的字符串值res/values/strings.xml:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <string name="alternates_for_a">àáâãäåæ</string>
</ressources>
Run Code Online (Sandbox Code Playgroud)

然后,在键盘布局定义中使用两者:

<Key android:codes="97" android:keyLabel="a"  
    android:popupKeyboard="@xml/kbd_popup_template"
    android:popupCharacters="@string/alternates_for_a" />
Run Code Online (Sandbox Code Playgroud)
  • 您还可以使用双击,三击,...功能为您正在点击的键生成替代项.为此,只需使用android密钥代码列表:

    <Key android:codes="97,224,230" .../>

a对于单击,将产生97 =' ',对于双击,将产生224 = à',æ对于三次击键,将产生230 =' '.

考虑双击的持续时间在android源代码中设置为800ms.不幸的是硬编码(我感觉有点高).

请注意,当双击时,它基本上发送' a',然后,在第二次点击它发送' à'.一些应用程序,不会喜欢这个.


小智 12

当我们只有一个弹出字符时,带有关闭按钮的弹出键盘很烦人.更简单的方法是像这样覆盖KeyboardView类的onLongPress方法.

@Override
protected boolean onLongPress(Key key) {
    if (key.codes[0] == '1') {
        getOnKeyboardActionListener().onKey('!', null);
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)


Fed*_*nov 7

如果你想在你的键上有一个文本,你可以在你的类中覆盖KeyboardView的onDraw()方法中执行它

 @Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    ...
    Paint paint = new Paint();
    paint.setTextAlign(Paint.Align.CENTER);
    paint.setTextSize(18);
    paint.setColor(Color.WHITE);
    //get all your keys and draw whatever you want
    List <Keyboard.Key> keys = getKeyboard().getKeys();
    for(Keyboard.Key key: keys) {
        if(key.label != null) {

            if (key.label.toString().equals("q") || key.label.toString().equals("Q"))
                canvas.drawText(String.valueOf(1), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("w") || key.label.toString().equals("W"))
                canvas.drawText(String.valueOf(2), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("e") || key.label.toString().equals("E"))
                canvas.drawText(String.valueOf(3), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("r") || key.label.toString().equals("R"))
                canvas.drawText(String.valueOf(4), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("t") || key.label.toString().equals("T"))
                canvas.drawText(String.valueOf(5), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("y") || key.label.toString().equals("Y"))
                canvas.drawText(String.valueOf(6), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("u") || key.label.toString().equals("U"))
                canvas.drawText(String.valueOf(7), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("i") || key.label.toString().equals("I"))
                canvas.drawText(String.valueOf(8), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("o") || key.label.toString().equals("o"))
                canvas.drawText(String.valueOf(9), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("p") || key.label.toString().equals("P"))
                canvas.drawText(String.valueOf(0), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else
            {}
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Sam*_*y T 5

对于任何试图通过它的可视区域之外攻驳回弹出键盘,我有一些运气把一个TouchListenerKeyboardView类内延伸InputMethodService

public class YourIME extends InputMethodService{
    @Override 
    public View onCreateInputView() {
        mInputView = (LatinKeyboardView) getLayoutInflater().inflate(R.layout.input, null);
        setLatinKeyboard(mQwertyKeyboard);

        mInputView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {

                if(motionEvent.getAction() == MotionEvent.ACTION_DOWN) {                        
                    mInputView.closing(); // Close popup keyboard if it's showing
                }
                return false;
            }
        });

        return mInputView;
    }
// The rest of your ime ...
}
Run Code Online (Sandbox Code Playgroud)

  • 这里有一个问题,如果您在键盘上的弹出窗口外部单击它会输出您单击的字母,需要在 if 中添加一个条件,只有在弹出窗口打开时才会发生 (2认同)