我已按照developer.android.com上关于Input Methods的示例进行了操作,并使用了SoftKeyboard示例应用程序。这些共同提供了有关创建简单键盘的足够信息。
我在API中看不到的是能够在标准键盘(LatinIME键盘)上为每个键创建备用/多个字符。
上图是长按“a”键的结果。当您长按一个键时,可以使用其他字符填充弹出窗口。
也可以在某些键上提供弹出提示,提示用户按住键以获取弹出菜单。
到目前为止,我还没有找到关于如何实现这一目标的单一信息来源,希望有人能够给我一个良好的开端,直到那时我将遵循内置键盘的源代码,看看我是否可以对它进行逆向工程。
修改:如果developer.android.com指向LatinIME键盘的链接未链接到Sheep的图片,则会有所帮助:) {{3的实际源代码}}
编辑2:更多作为参考而不是其他任何内容,这是我认为通常的longPress操作为了在LatinIME.java中显示弹出式键盘而执行的序列:
onTouchEvent()
onModifiedTouchEvent()
mHandkler.handleMessage() with MSG_LONGPRESS
openPopupIfRequired()
onLongPress()
编辑3:
我仍然没有想到这一点 - 如何向键添加标签建议?答案表明它没有内置到API中,事实上我还没有找到代码来执行此操作。但是,2.3.4(API 10)上的键盘显示正在实现此功能:
非常想弄清楚IT是如何做到的,但它不是我能看到的onDraw()
方法中的任何地方 - 这让我相信它是在KeyboardView元素之外编写的。然而,我无法找到用于在内置键盘上显示KeyboardView元素的layout
文件 - 如果有人知道在哪里找到这个可能会给我提供我需要的线索。
编辑4:移动键预览问题,因为它稍微偏离主题:
答案 0 :(得分:51)
实施备用密钥弹出窗口
对于您希望拥有弹出式键盘的每个键,您应该定义popupCharacters和popupKeyboard:
/res/xml/[Keyboard].xml
<Key android:keyLabel="("
android:popupKeyboard="@xml/keyboard_popup_template"
android:popupCharacters="[{<" />
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>
为备用键弹出设置样式:
如果要更改弹出窗口的布局/样式(默认为@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源代码)的唯一解决方案如下:
将<KeyboardView>
标记包含<FrameLayout>
标记,其高度由keyHeight乘以行数指定。在这个标签里面,我只是创建了一个LinearLayout来保存行,然后为包含TextView的每一行创建一个LinearLayout,其权重等于为每个<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>
产生这个:
在我设法以与系统键盘相同的方式实现此功能之前,我不会高兴!
答案 1 :(得分:14)
从我自己尝试编写软键盘的过程中我发现:
KeyboardView
并基本上编写大部分绘图代码。不幸的是,你不能通过覆盖一些关键方法来做到这一点,因为几乎所有东西都是私有的。你可能想看看(并从中借用一些代码:
(base)/core/java/android/inputmethodservice/KeyboardView.java
(android核心代码回购)(apps)/other/LatinIME/LatinKeyboardView.java
(android core apps repo)请注意,android.kernel.org上的绵羊会告诉你由于破解程序而关闭了回购,但是在其他地方有代码的镜像(遗憾地丢失了链接)
KeyboardView
对阴影键提示有 no 支持,您必须编写自己的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>
声明包含此键盘上所需键的字符串值res/values/strings.xml
:
<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" />
您还可以使用双击,三击,...功能为您正在点击的键生成替代项。为此,只需使用列表作为android密码:
<Key android:codes="97,224,230" .../>
将生成97 ='a
',对于双击,<=> à
',对于三次点按,则为230 ='æ
'。
在Android源代码中,考虑双击的持续时间设置为800毫秒。不幸的是硬编码(我感觉有点高)。
请注意,双击时,它基本上先发送“a
”,然后在第二次点按时发送“à
”。一些应用程序,不会喜欢这个。
答案 2 :(得分:12)
当我们只有一个弹出字符时,带有关闭按钮的弹出式键盘很烦人。 更简单的方法是覆盖KeyboardView类的onLongPress方法,如下所示。
@Override
protected boolean onLongPress(Key key) {
if (key.codes[0] == '1') {
getOnKeyboardActionListener().onKey('!', null);
return true;
}
}
答案 3 :(得分: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
{}
}
}
}
答案 4 :(得分:5)
对于任何试图通过点击其视图区域以外的方式来解除弹出式键盘的人,我有幸在TouchListener
内的KeyboardView
内部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 ...
}
< / p>
TSQLLog
答案 5 :(得分:0)
如果你想在你的密钥顶部有一个文本,你可以在你的类中的onDraw()方法中进行扩展KeyboardView我做了类似这样的事情也许这可以帮助某人
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d("LatinKeyboardView", "onDraw");
Paint paint = new Paint();
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(30);
paint.setColor(Color.LTGRAY);
List<Key> keys = getKeyboard().getKeys();
for (Key key : keys) {
if (key.label != null) {
switch (key.codes[0]) {
//qQ
case 81:
case 113:
case 1602:
case 1618:
canvas.drawText(String.valueOf(1), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//wW
case 87:
case 119:
case 1608:
case 1572:
canvas.drawText(String.valueOf(2), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//eE
case 69:
case 101:
case 1593:
case 1617:
canvas.drawText(String.valueOf(3), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//rR
case 82:
case 114:
case 1585:
case 1681:
canvas.drawText(String.valueOf(4), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//tT
case 84:
case 116:
case 1578:
case 1657:
canvas.drawText(String.valueOf(5), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//yY
case 89:
case 121:
case 1746:
case 1552:
canvas.drawText(String.valueOf(6), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//uU
case 85:
case 117:
case 1569:
case 1574:
canvas.drawText(String.valueOf(7), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//iI
case 73:
case 105:
case 1740:
case 1648:
canvas.drawText(String.valueOf(8), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//oO
case 79:
case 111:
case 1729:
case 1731:
canvas.drawText(String.valueOf(9), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//pP
case 80:
case 112:
case 1662:
case 1615:
canvas.drawText(String.valueOf(0), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//aA
case 65:
case 97:
case 1575:
case 1570:
canvas.drawText("@", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//sS
case 83:
case 115:
case 1587:
case 1589:
canvas.drawText("#", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//dD
case 68:
case 100:
case 1583:
case 1672:
canvas.drawText("$", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//fF
case 70:
case 102:
case 1601:
case 1613:
canvas.drawText("%", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//gG
case 71:
case 103:
case 1711:
case 1594:
canvas.drawText("&", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//hH
case 72:
case 104:
case 1726:
case 1581:
canvas.drawText("-", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//jJ
case 74:
case 106:
case 1580:
case 1590:
canvas.drawText("+", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//kK
case 75:
case 107:
case 1705:
case 1582:
canvas.drawText("(", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//lL
case 76:
case 108:
case 1604:
case 1614:
canvas.drawText(")", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//zZ
case 90:
case 122:
case 1586:
case 1584:
canvas.drawText("*", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//xX
case 88:
case 120:
case 1588:
case 1679:
canvas.drawText("\"", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//cC
case 67:
case 99:
case 1670:
case 1579:
canvas.drawText("\'", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//vV
case 86:
case 118:
case 1591:
case 1592:
canvas.drawText(":", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//bB
case 66:
case 98:
case 1576:
case 1616:
canvas.drawText(";", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//nN
case 78:
case 110:
case 1606:
case 1722:
canvas.drawText("!", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
//mM
case 77:
case 109:
case 1605:
case 1611:
canvas.drawText("?", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
break;
}
}
}
}
根据您的选择调整这些轴
int keyXAxis = 25;
int keyYAxis = 50;
答案 6 :(得分:0)
根据这里的答案,我所做的是:
public class MyKeyboardView extends KeyboardView {
private Keyboard.Key longPressedKey = null;
public MyKeyboardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyKeyboardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(35);
paint.setColor(Color.BLACK);
//get all your keys and draw whatever you want
List<Keyboard.Key> keys = getKeyboard().getKeys();
for (Keyboard.Key key : keys) {
if (key.popupCharacters != null && key.popupCharacters.length() > 0) {
canvas.drawText(key.popupCharacters.toString(), key.x + (key.width / 2) + 10, key.y + 30, paint);
}
}
}
@Override
protected boolean onLongPress(Keyboard.Key key) {
if (key.popupCharacters != null && key.popupCharacters.length() > 0)
longPressedKey = key;
return super.onLongPress(key);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP) {
if (longPressedKey != null) {
// TODO: Try detecting what key the finger is above if there are many popupCharacters
getOnKeyboardActionListener().onKey((longPressedKey.popupCharacters.charAt(0)), null);
dismissPopupKeyboard();
longPressedKey = null;
}
}
return true; // Required for recieving subsequent events (ACTION_MOVE, ACTION_UP)
}
private void dismissPopupKeyboard() {
// Because of KeyboardView.dismissPopupKeyboard() is private, we are doing this trick (KeyboardView.click() calls dismissPopupKeyboard()).
// TODO: Make this like a normal human. We will need to create the popup on our own like the way the keyboard does it.
onClick(new View(getContext()));
}
和
在使用KeyboardView时,将其更改为MyKeyboardView,并带有以下额外参数-android:popupLayout="@layout/keyboard_popup_keyboard"
这是keyboard_popup_keyboard.xml(很重要,因此不会有取消按钮)
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<android.inputmethodservice.KeyboardView
android:id="@android:id/keyboardView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/popup_key_color"
android:keyPreviewLayout="@layout/key_preview"
android:keyPreviewOffset="0px"
android:keyPreviewHeight="@dimen/key_preview_height"
android:keyTextColor="@color/darkGray"
android:keyBackground="@drawable/key_background_selector"
android:shadowRadius="0.0"
android:horizontalGap="0px"
android:verticalGap="0px" />
</LinearLayout>