on
Italy
- Get link
- X
- Other Apps
Service
in AndroidManifest.xml that uses the BIND_INPUT_METHOD
permission, and responds to the action android.view.InputMethod
.application
tag of the manifest:
1
2
3
4
5
6
7
8
9
| < service android:name = ".SimpleIME" android:label = "@string/simple_ime" 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 > |
service
tag in the manifest file containes a meta-data
tag that references an XML file named method.xml. Without this file, the Android operating system won't recognize our Service
as a valid IME service. The file contains details about the input
method and its subtypes. For our keyboard, we define a single
subtype for the en_US locale. Create the directory res/xml if it doesn't exist, and add the file method.xml to it. The contents of the file should be:
1
2
3
4
5
6
7
|
< subtype android:label = "@string/subtype_en_US" android:imeSubtypeLocale = "en_US" android:imeSubtypeMode = "keyboard" /> </ input-method > |
1
2
3
4
5
| < resources > < string name = "app_name" >SimpleKeyboard</ string > < string name = "simple_ime" >Simple IME</ string > < string name = "subtype_en_US" >English (US)</ string > </ resources > |
KeyboardView
. The layout_alignParentBottom
attribute is set to true
so that keyboard appears at the bottom of the screen.
1
2
3
4
5
6
7
8
9
|
< android.inputmethodservice.KeyboardView android:id = "@+id/keyboard" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_alignParentBottom = "true" android:keyPreviewLayout = "@layout/preview" /> |
keyPreviewLayout
is the layout of the short-lived pop-up that shows up whenever a key on the keyboard is pressed. It contains a single TextView
. Create a file named res/layout/preview.xml and add the following to it:
01
02
03
04
05
06
07
08
09
10
|
android:layout_width = "match_parent" android:layout_height = "match_parent" android:gravity = "center" android:background = "#ffff00" android:textStyle = "bold" android:textSize = "30sp" > </ TextView > |
keyLabel
: This attribute contains the text that is displayed on the key.codes
: This attribute contains the unicode values of the characters that the key represents.codes
attribute should have the value 97 and the keyLabel
attribute should be set to A.keyEdgeFlags
: This attribute can take the value left
or right
. This attribute is usually added to the leftmost and rightmost keys of a row.keyWidth
: This attribute defines the width of a key. It's usually defined as a percentage value.isRepeatable
: If this attribute is set to true
, long-pressing the key will repeat the action of the key multiple times. It is usually set to true
for the delete and spacebar keys.
01
02
03
04
05
06
07
08
09
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
53
54
55
56
57
58
59
60
61
62
| android:keyWidth = "10%p" android:horizontalGap = "0px" android:verticalGap = "0px" android:keyHeight = "60dp" > < Row > < Key android:codes = "49" android:keyLabel = "1" android:keyEdgeFlags = "left" /> < Key android:codes = "50" android:keyLabel = "2" /> < Key android:codes = "51" android:keyLabel = "3" /> < Key android:codes = "52" android:keyLabel = "4" /> < Key android:codes = "53" android:keyLabel = "5" /> < Key android:codes = "54" android:keyLabel = "6" /> < Key android:codes = "55" android:keyLabel = "7" /> < Key android:codes = "56" android:keyLabel = "8" /> < Key android:codes = "57" android:keyLabel = "9" /> < Key android:codes = "48" android:keyLabel = "0" android:keyEdgeFlags = "right" /> </ Row > < Row > < Key android:codes = "113" android:keyLabel = "q" android:keyEdgeFlags = "left" /> < Key android:codes = "119" android:keyLabel = "w" /> < Key android:codes = "101" android:keyLabel = "e" /> < Key android:codes = "114" android:keyLabel = "r" /> < Key android:codes = "116" android:keyLabel = "t" /> < Key android:codes = "121" android:keyLabel = "y" /> < Key android:codes = "117" android:keyLabel = "u" /> < Key android:codes = "105" android:keyLabel = "i" /> < Key android:codes = "111" android:keyLabel = "o" /> < Key android:codes = "112" android:keyLabel = "p" android:keyEdgeFlags = "right" /> </ Row > < Row > < Key android:codes = "97" android:keyLabel = "a" android:keyEdgeFlags = "left" /> < Key android:codes = "115" android:keyLabel = "s" /> < Key android:codes = "100" android:keyLabel = "d" /> < Key android:codes = "102" android:keyLabel = "f" /> < Key android:codes = "103" android:keyLabel = "g" /> < Key android:codes = "104" android:keyLabel = "h" /> < Key android:codes = "106" android:keyLabel = "j" /> < Key android:codes = "107" android:keyLabel = "k" /> < Key android:codes = "108" android:keyLabel = "l" /> < Key android:codes = "35,64" android:keyLabel = "\# \@" android:keyEdgeFlags = "right" /> </ Row > < Row > < Key android:codes = "-1" android:keyLabel = "CAPS" android:keyEdgeFlags = "left" /> < Key android:codes = "122" android:keyLabel = "z" /> < Key android:codes = "120" android:keyLabel = "x" /> < Key android:codes = "99" android:keyLabel = "c" /> < Key android:codes = "118" android:keyLabel = "v" /> < Key android:codes = "98" android:keyLabel = "b" /> < Key android:codes = "110" android:keyLabel = "n" /> < Key android:codes = "109" android:keyLabel = "m" /> < Key android:codes = "46" android:keyLabel = "." /> < Key android:codes = "63,33,58" android:keyLabel = "\? ! :" android:keyEdgeFlags = "right" /> </ Row > < Row android:rowEdgeFlags = "bottom" > < Key android:codes = "44" android:keyLabel = "," android:keyWidth = "10%p" android:keyEdgeFlags = "left" /> < Key android:codes = "47" android:keyLabel = "/" android:keyWidth = "10%p" /> < Key android:codes = "32" android:keyLabel = "SPACE" android:keyWidth = "40%p" android:isRepeatable = "true" /> < Key android:codes = "-5" android:keyLabel = "DEL" android:keyWidth = "20%p" android:isRepeatable = "true" /> < Key android:codes = "-4" android:keyLabel = "DONE" android:keyWidth = "20%p" android:keyEdgeFlags = "right" /> </ Row > </ Keyboard > |
codes
attribute. Negative values are equal to predefined constants in the Keyboard
class. For example, the value -5
is equal to the value of Keyboard.KEYCODE_DELETE
.Service
ClassInputMethodService
class and implement the OnKeyboardActionListener
interface. The OnKeyboardActionListener
interface contains the methods that are called when keys of the soft keyboard are tapped or pressed.SimpleIME
class should have three member variables:KeyboardView
referencing the view defined in the layoutKeyboard
instance that is assigned to the KeyboardView
boolean
telling us if the caps lock is enabledOnKeyboardActionListener
interface, the SimpleIME
class should look like this:
01
02
03
04
05
06
07
08
09
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
| public class SimpleIME extends InputMethodService implements OnKeyboardActionListener{ private KeyboardView kv; private Keyboard keyboard; private boolean caps = false ; @Override public void onKey( int primaryCode, int [] keyCodes) { } @Override public void onPress( int primaryCode) { } @Override public void onRelease( int primaryCode) { } @Override public void onText(CharSequence text) { } @Override public void swipeDown() { } @Override public void swipeLeft() { } @Override public void swipeRight() { } @Override public void swipeUp() { } } |
onCreateInputView
method is called. All the member variables of the Service
can be initialized here. Update the implementation of the onCreateInputView
method as shown below:
1
2
3
4
5
6
7
8
| @Override public View onCreateInputView() { kv = (KeyboardView)getLayoutInflater().inflate(R.layout.keyboard, null ); keyboard = new Keyboard( this , R.xml.qwerty); kv.setKeyboard(keyboard); kv.setOnKeyboardActionListener( this ); return kv; } |
AudioManager
class to play the sounds. The Android SDK includes a few default sound effects for key presses and those are used in the playClick
method.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
| private void playClick( int keyCode){ AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE); switch (keyCode){ case 32 : am.playSoundEffect(AudioManager.FX_KEYPRESS_SPACEBAR); break ; case Keyboard.KEYCODE_DONE: case 10 : am.playSoundEffect(AudioManager.FX_KEYPRESS_RETURN); break ; case Keyboard.KEYCODE_DELETE: am.playSoundEffect(AudioManager.FX_KEYPRESS_DELETE); break ; default : am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD); } } |
onKey
method so that our keyboard app can communicate with input fields (usually EditText
views) of other applications.getCurrentInputConnection
method is used to get a connection to the input field of another
application. Once we have the connection, we can use the following
methods:commitText
to add one or more characters to the input fielddeleteSurroundingText
to delete one or more characters of the input fieldsendKeyEvent
to send events, like KEYCODE_ENTER
, to the external applicationonKey
method is called with the unicode value of the key as one of its
parameters. Based on this value, the keyboard performs one of the
following actions:KEYCODE_DELETE
, one character to the left of the cursor is deleted using the deleteSurroundingText
method.KEYCODE_DONE
, a KEYCODE_ENTER
key event is fired.KEYCODE_SHIFT
, the value of the caps
variable is changed and the shift state of the keyboard is updated using the setShifted
method. The keyboard needs to be redrawn when the state changes so that the labels of the keys are updated. The invalidateAllKeys
method is used to redraw all keys.caps
variable is set to true
, then the character is converted to uppercase.onKey
method so that it looks like this:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| @Override public void onKey( int primaryCode, int [] keyCodes) { InputConnection ic = getCurrentInputConnection(); playClick(primaryCode); switch (primaryCode){ case Keyboard.KEYCODE_DELETE : ic.deleteSurroundingText( 1 , 0 ); break ; case Keyboard.KEYCODE_SHIFT: caps = !caps; keyboard.setShifted(caps); kv.invalidateAllKeys(); break ; case Keyboard.KEYCODE_DONE: ic.sendKeyEvent( new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)); break ; default : char code = ( char )primaryCode; if (Character.isLetter(code) && caps){ code = Character.toUpperCase(code); } ic.commitText(String.valueOf(code), 1 ); } } |
Activity
, which means that it won't show up in the launcher. To use it, it should first be activated in the device's Settings.
Comments
Post a Comment