android自定义键盘

Posted by alonealice on 2017-03-04

在某些安全性比较高的软件,如银行的相关软件中,输入密码等操作时往往会弹出自定义的软键盘。如果输入的只有数字,开发者往往会通过自定义View和TextView的方式实现,这种方式可以避免第三方键盘的调起。但是如果需要在editview中实现时,就需要实现自己的键盘。

实现自定义键盘主要有两个类:Keyboard和KeyboardView。

Keyboard类主要是用于监听虚拟键盘,它里面有内部类Key和Row,用以记录按键和行的相关信息。KeyBoardView则主要是根据Keyboard中按键的信息,绘制所有的key,同时根据触摸位置,计算出点击的Key,通过OnKeyboardActionListener回调进行事件和string值的传递。

定义KeyboardView

首先要在layout文件夹中定义KeyboardView:

1
2
3
4
5
6
7
8
9
10
11
12
13
<android.inputmethodservice.KeyboardView
android:id="@+id/keyboard"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:keyBackground="@drawable/shape_key_background"
android:labelTextSize="15dp"
android:keyPreviewHeight="50dp"
android:popupLayout="@layout/layout_poplayout"
android:keyPreviewLayout="@layout/layout_key_preview"/>

这里有几个重要的定义,一个是keyBackground,这个是按键的背景,一个是 keyPreviewLayout,这个是按键之后的预览样式,还有一个是popupLayout,这个是长按之后的预览样式。同时,这里还有一个要注意的是,这边的KeyboardView的id和popupLayout里面的KeyboardView的id一定是android:id="@+id/keyboard",不然会无法找到KeyboardView。

自定义键盘的样式Keyboard

定义好KeyboardView之后,需要定义里面具体键盘的样式。在res目录下xml文件夹,当中新建一个xml文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="20%p"
android:horizontalGap="1.5%p"
android:verticalGap="7dp"
android:keyHeight="60dp"
>
<Row>
<Key android:codes="45" android:keyLabel="-" android:keyWidth="15.5%p"/>
<Key android:codes="49" android:keyLabel="1"/>
<Key android:codes="50" android:keyLabel="2"/>
<Key android:codes="51" android:keyLabel="3"/>
<Key android:codes="119" android:keyLabel="w" android:popupCharacters="@string/symbol_w" android:popupKeyboard="@layout/layout_poplayout"/>
<Key android:codes="8" android:keyIcon="@drawable/key_delete" android:keyWidth="15.5%p" android:isRepeatable="true"/>
</Row>
...
</Keyboard>

里面有KeyboardKeyboard作为根节点,定义了keyWidth,keyHeight和上下的偏移量。里面有row节点和key节点。key节点和Row节点都可以再次定义相应的行高和宽高,同时,还可以在key中定义其按下的值codes,key显示的值keylabel,key的图标keyIcon,长按的值popupCharacters和长按样式popupKeyboard等属性。里面有一个重要的属性isRepeatable,表示长按后是否有连续点击的效果,比如删除按钮就会有该效果。

定义InputMethodService

定义好键盘的样式后,需要将键盘显示出来,这时就需要定义InputMethodService。

自定义一个类继承InputMethodService,并且实现OnKeyboardActionListener接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class ZFIme extends InputMethodService implements KeyboardView.OnKeyboardActionListener {

@Override
public View onCreateInputView() {
keyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.keyboard, null);
mKeyboard = new Keyboard(this, R.xml.keys);
keyboardView.setKeyboard(mKeyboard);
keyboardView.setOnKeyboardActionListener(this);
return keyboardView;
}

@Override
public void onPress(int primaryCode) {

}

@Override
public void onRelease(int primaryCode) {

}

@Override
public void onKey(int primaryCode, int[] keyCodes) {
getCurrentInputConnection().commitText(Character.toString((char) primaryCode),1);
}

@Override
public void onText(CharSequence text) {

}


@Override
public void swipeLeft() {

}

@Override
public void swipeRight() {

}

@Override
public void swipeDown() {

}

@Override
public void swipeUp() {

}
}

在onCreateInputView方法中,获取刚才定义的KeyboardView,并且创建keyboard,传入定义好的键盘keys,将keyboard设置给KeyboardView,并且返回。

同时,在onkey方法中将按下的信息传递出去getCurrentInputConnection()方法返回一个InputConnection实例,可以通过它对调起键盘的edittext进行相应的操作,比如文字的输入、删除等。

注册服务

将刚才定义的InputMethodService注册到AndroidManifest中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//首先要申请绑定输入的权限
<permission android:name="android.permission.BIND_INPUT_METHOD"></permission>


//注册service
<service
android:name=".ZFIme"
android:permission="android.permission.BIND_INPUT_METHOD"
>
<meta-data android:name="android.view.im"
android:resource="@xml/method"/>
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
</service>

在xml中定义:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android">

<subtype
android:label="正风键盘"
android:imeSubtypeLocale="english"
android:imeSubtypeMode="keyboard">
</subtype>
</input-method>

到这里为止,我们就可以在设置里面找到自己定义的键盘,在输入时切换到自己的键盘,实现很多自己的功能。但是,从上面的代码可以看到,这些是自定义键盘最基础的步骤,如果需要实现自己的功能,比如整个键盘的背景(系统默认为黑色),自定义的长按功能,多个字符同时在一个key上显示等功能,只是这些是远远不够的,需要定义KeyboardView和Keyboard,至于这些实现这些,请等待后续文章。