System keyboard
This answer tells how to make a custom system keyboard that can be used in any app that a user has installed on their phone. If you want to make a keyboard that will only be used within your own app, then see my other answer.
The example below will look like this. You can modify it for any keyboard layout.
The following steps show how to create a working custom system keyboard. As much as possible I tried to remove any unnecessary code. If there are other features that you need, I provided links to more help at the end.
1. Start a new Android project
I named my project "Custom Keyboard". Call it whatever you want. There is nothing else special here. I will just leave the MainActivity
and "Hello World!" layout as it is.
2. Add the layout files
Add the following two files to your app's res/layout
folder:
- keyboard_view.xml
- key_preview.xml
keyboard_view.xml
This view is like a container that will hold our keyboard. In this example there is only one keyboard, but you could add other keyboards and swap them in and out of this KeyboardView
.
<?xml version="1.0" encoding="utf-8"?>
<android.inputmethodservice.KeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keyboard_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:keyPreviewLayout="@layout/key_preview"
android:layout_alignParentBottom="true">
</android.inputmethodservice.KeyboardView>
key_preview.xml
The key preview is a layout that pops up when you press a keyboard key. It just shows what key you are pressing (in case your big, fat fingers are covering it). This isn't a multiple choice popup. For that you should check out the Candidates view.
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@android:color/white"
android:textColor="@android:color/black"
android:textSize="30sp">
</TextView>
3. Add supporting xml files
Create an xml
folder in your res
folder. (Right click res
and choose New > Directory.)
Then add the following two xml files to it. (Right click the xml
folder and choose New > XML resource file.)
- number_pad.xml
- method.xml
number_pad.xml
This is where it starts to get more interesting. This Keyboard
defines the layout of the keys.
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="20%p"
android:horizontalGap="5dp"
android:verticalGap="5dp"
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" android:keyEdgeFlags="right"/>
</Row>
<Row>
<Key android:codes="54" android:keyLabel="6" android:keyEdgeFlags="left"/>
<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="-5"
android:keyLabel="DELETE"
android:keyWidth="40%p"
android:keyEdgeFlags="left"
android:isRepeatable="true"/>
<Key android:codes="10"
android:keyLabel="ENTER"
android:keyWidth="60%p"
android:keyEdgeFlags="right"/>
</Row>
</Keyboard>
Here are some things to note:
keyWidth
: This is the default width of each key. The 20%p
means that each key should take up 20% of the width of the parent. It can be overridden by individual keys, though, as you can see happened with the Delete and Enter keys in the third row.
keyHeight
: It is hard coded here, but you could use something like @dimen/key_height
to set it dynamically for different screen sizes.
Gap
: The horizontal and vertical gap tells how much space to leave between keys. Even if you set it to 0px
there is still a small gap.
codes
: This can be a Unicode or custom code value that determines what happens or what is input when the key is pressed. See keyOutputText
if you want to input a longer Unicode string.
keyLabel
: This is the text that is displayed on the key.
keyEdgeFlags
: This indicates which edge the key should be aligned to.
isRepeatable
: If you hold down the key it will keep repeating the input.
method.xml
This file tells the system the input method subtypes that are available. I am just including a minimal version here.
<?xml version="1.0" encoding="utf-8"?>
<input-method
xmlns:android="http://schemas.android.com/apk/res/android">
<subtype
android:imeSubtypeMode="keyboard"/>
</input-method>
4. Add the Java code to handle key input
Create a new Java file. Let's call it MyInputMethodService
. This file ties everything together. It handles input received from the keyboard and sends it on to whatever view is receiving it (an EditText
, for example).
public class MyInputMethodService extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
@Override
public View onCreateInputView() {
// get the KeyboardView and add our Keyboard layout to it
KeyboardView keyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.keyboard_view, null);
Keyboard keyboard = new Keyboard(this, R.xml.number_pad);
keyboardView.setKeyboard(keyboard);
keyboardView.setOnKeyboardActionListener(this);
return keyboardView;
}
@Override
public void onKey(int primaryCode, int[] keyCodes) {
InputConnection ic = getCurrentInputConnection();
if (ic == null) return;
switch (primaryCode) {
case Keyboard.KEYCODE_DELETE:
CharSequence selectedText = ic.getSelectedText(0);
if (TextUtils.isEmpty(selectedText)) {
// no selection, so delete previous character
ic.deleteSurroundingText(1, 0);
} else {
// delete the selection
ic.commitText("", 1);
}
break;
default:
char code = (char) primaryCode;
ic.commitText(String.valueOf(code), 1);
}
}
@Override
public void onPress(int primaryCode) { }
@Override
public void onRelease(int primaryCode) { }
@Override
public void onText(CharSequence text) { }
@Override
public void swipeLeft() { }
@Override
public void swipeRight() { }
@Override
public void swipeDown() { }
@Override
public void swipeUp() { }
}
Notes:
- The
OnKeyboardActionListener
listens for keyboard input. It is also requires all those empty methods in this example.
- The
InputConnection
is what is used to send input to another view like an EditText
.
5. Update the manifest
I put this last rather than first because it refers to the files we already added above. To register your custom keyboard as a system keyboard, you need to add a service
section to your AndroidManifest.xml file. Put it in the application
section after activity
.
<manifest ...>
<application ... >
<activity ... >
...
</activity>
<service
android:name=".MyInputMethodService"
android:label="Keyboard Display Name"
android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter>
<action android:name="android.view.InputMethod"/>
</intent-filter>
<meta-data
android:name="android.view.im"
android:resource="@xml/method"/>
</service>
</application>
</manifest>
That's it! You should be able to run your app now. However, you won't see much until you enable your keyboard in the settings.
6. Enable the keyboard in Settings
Every user who wants to use your keyboard will have to enable it in the Android settings. For detailed instructions on how to do that, see the following link:
Here is a summary: