使用每个键多个/备用字符创build一个SoftKeyboard

我已经遵循了关于input法的 developer.android.com上的示例,并使用SoftKeyboard示例应用程序进行播放。 这些共同提供了足够的关于创build简单键盘的信息。

我在API中看不到的是,可以在标准键盘(LatinIME键盘)上为每个键创build替代/多个字符。

在这里输入图像描述

上图是长按“a”键的结果。 当你长按一个键时,可以使用替代字符填充popup框。

在这里输入图像描述

也可以在某些按键上popup一个提示,提示用户按住一个按键来获得popup式菜单。

到目前为止,我还没有find关于如何实现的单一信息来源,希望有人能够给我一个开始,直到那时我会遵循内置键盘的源代码,看看我是否可以逆向工程它。

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

编辑2:更多作为参考比其他任何事情,这是序列我相信一个通常的longPress行动通过为了显示在KeyboardView.javapopup式键盘:

onTouchEvent() onModifiedTouchEvent() mHandkler.handleMessage() with MSG_LONGPRESS openPopupIfRequired() onLongPress() 

编辑3:

我仍然没有想到这一点 – 你如何添加标签build议的关键? 一个答案表明,它不是内置到API中,实际上我没有find代码来做到这一点。 但2.3.4(API 10)上的键盘显示了正在实现的function:

在这里输入图像描述

非常想知道IT是如何实现的,但是我不能看到onDraw()方法中的任何地方 – 这使我相信它正在被编写在KeyboardView元素之外。 我不能findlayout文件用于显示内置的键盘上的KeyboardView元素 – 如果有人知道在哪里可以find这可能会给我线索我需要的。

编辑4:移动键在这里预览的问题,因为它是有点偏离主题:

如何禁用SoftKeyboard键预览窗口?

实现备用按键popup:

对于每个你想要有一个popup式键盘的键,你应该定义popupCharacters和popupKeyboard :

/res/xml/[Keyboard].xml

 <Key android:keyLabel="(" android:popupKeyboard="@xml/keyboard_popup_template" android:popupCharacters="[{&lt;" /> 

popupKeyboard是在包含替代键的popup窗口中使用的键盘的XML表示forms:

/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> 

devise替代键popup式样:

如果要更改popup窗口的布局/样式(默认为@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" /> 

实现关键预览覆盖:

我已经能够敲门显示关键预览(没有完全重写KeyboardView源代码)的唯一解决scheme如下:

<FrameLayout>包装<KeyboardView>标签,其高度由keyHeight乘以行数指定。 在这个标签中,我简单地创build了一个LinearLayout来存放行,然后一个LinearLayout包含一个TextView,它的权重等于每个<Key>指定的%p值:

 <TextView android:text="!" style="@style/Custom.Widget.KeyboardKeyOverlay" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="10"/> 

和风格:

 <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> 

这产生这个:

在这里输入图像描述

直到我像系统键盘那样设法实现这个function,我才开心!

从我自己编写软键盘的尝试来看,我发现:

  • 尼斯/金光闪闪的function通常需要扩展KeyboardView并基本上写大部分的绘图代码。 不幸的是,你不能通过重写一些关键的方法做到这一点, 你可能想看看(并借用一些代码:
    • (base)/core/java/android/inputmethodservice/KeyboardView.java (android核心代码回购)
    • (apps)/other/LatinIME/LatinKeyboardView.java (android核心应用程序回购)

请注意,android.kernel.org上的羊在那里告诉你,回购是由于cookiesclosures,但在别处的代码镜像(不幸的是失去了链接)

  • 基础KeyboardView 支持阴影键提示,您必须编写您自己的KeyboardView才能有机会覆盖onDraw()方法。

现在你可以做什么:

  • 你可以通过提供关键字的图片来解决这个问题:使用xml <Key ... android:keyIcon="@drawable/this_key_icon_file />这样做,不幸的是,问题)。

  • 您可以使用(和configuration外观)长按出现的popup式键盘。

声明一个键盘模板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> 

在这个键盘res/values/strings.xml声明包含你想要的键的string值:

 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="alternates_for_a">àáâãäåæ</string> </ressources> 

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

 <Key android:codes="97" android:keyLabel="a" android:popupKeyboard="@xml/kbd_popup_template" android:popupCharacters="@string/alternates_for_a" /> 
  • 您还可以使用双击,三击,…function为您正在点击的按键生成交替。 为此,只需使用android keycodes的列表

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

对于单抽头将产生97 =“ a ”,对于双抽头将产生224 =“ à ”,对于三抽头将产生230 =“ æ ”。

Android源代码中考虑双击的时间长度设置为800ms。 不幸的是硬编码(有点高,我觉得)。

请注意,当双击时,它基本上首先发送一个' a ',然后在第二个水龙头发送' à '。 有些应用程序,不会喜欢这个。

当我们只有一个popup式字符时,那个带有closuresbutton的popup式键盘很烦人。 更简单的方法是像这样覆盖KeyboardView类的onLongPress方法。

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

如果你想在你的键上有一个文本,你可以在你的类的onDraw()方法中重写KeyboardView

  @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 {} } } } 

对于任何试图通过点击外部视图区域来closurespopup式键盘的人来说,我已经有一些运气将TouchListener放在类TouchListener中的KeyboardView

 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 ... }