Problem

Google’s sample keyboard project is a little out of date. It’s a very helpful starting point but requires some minor changes to get it working as expected. On top of that, many of the common customizations are spread out across a wide array of stack overflow posts.

Solution

I’ve made some minor updates to Google’s base keyboard example and applied some of the common customizations to the keyboard. This only took a couple of hours to put together but required a number of different resources including blogs, documentation and Stackoverflow. This keyboard contains styling, predictive complete spell check and alternate keys. There is still a lot of room for improvement but this is a much better starting point.

Keyboard animation

Source Code

Overview

There are already resources that walk through aspects of the keyboard code in great detail. At a high level you have a class that extends Keyboard, a KeyboardView and a KeyboardService that extends InputMethodService. On top of that it’s really just adding your icons, layout and XML files. Most of the styling can be done in the input.xml file.

Popup Keyboard Layout:

When you add pop-up keys (alternate keys that appear on long press) you’re actually creating a new keyboard for the pop-up. It was a bit confusing at first but makes sense after you take a look at the code. The new keyboard is automatically created and displayed as a modal above your existing keyboard.

Popup Keyboard

Snipet from original keyboard XML template:

...
<Key android:codes="46,44" android:keyLabel=". ,"
     android:keyWidth="15%p" android:popupCharacters=".,?!#@" 
     android:popupKeyboard="@xml/keyboard_popup_template"/>
...

Popup keyboard XML template:

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="10%p"
    android:horizontalGap="0px"
    android:verticalGap="0px"
    android:keyHeight="56dp">
</Keyboard>

Popup keyboard layout file (set in the input.xml keyboard layout):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="@color/colorPrimaryDark">
    <android.inputmethodservice.KeyboardView
        android:id="@android:id/keyboardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:keyPreviewLayout="@layout/preview"
        android:popupLayout="@layout/keyboard_popup_layout"
        android:keyBackground="@drawable/key_background"
        android:keyTextColor="#333"
        android:background="@color/colorPrimaryDark"
        android:keyTextSize="22sp"/>
    <ImageButton android:id="@android:id/closeButton"
        android:background="@android:color/transparent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:clickable="true"
        android:src="@drawable/ic_close_black" />
</LinearLayout>

Next Steps

The predictive text appears over the top of content on the screen. I’ve been reading that it’s easier to manage by including it in the keyboard layout instead of using the candidates view. This would give more control over the behavior and prevent content on the screen from being covered up. In addition to that, predictive text doesn’t work correctly if you hit backspace half way through a word. The text selection position should be updated to check for white space and more intelligently select the word. This implementation uses the dictionary which seemed like a reasonable predictive text option but it could be updated to include a app specific dictionary of words that builds up over time.

I’ve removed the preview text in this example (the semi-transparent pop-up that appears just above the letter as you type). The pop-up was animating around the screen and not behaving like the new Android material keyboard. It didn’t look easy to modify this in the KeyboardView, it would probably be better to write this logic from scratch if you need it.

Resources

Getting Started:
https://developer.android.com/guide/topics/text/creating-input-method.html
http://www.fampennings.nl/maarten/android/09keyboard/index.htm

Sample Code:
https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/
https://github.com/blackcj/AndroidCustomKeyboard

Spell Checker:
https://android.googlesource.com/platform/development/+/master/samples/SpellChecker/HelloSpellChecker/src/com/example/android/hellospellchecker/HelloSpellCheckerActivity.java
https://developer.android.com/guide/topics/text/spell-checker-framework.html

Other:
https://github.com/zeuxisoo/android-emoji-keyboard
https://stackoverflow.com/questions/7752580/creating-a-softkeyboard-with-multiple-alternate-characters-per-key

Stackoverflow Posts:
https://stackoverflow.com/questions/30654687/how-can-i-show-the-candidates-view-under-the-android-soft-keyboard
https://stackoverflow.com/questions/18180136/how-to-change-background-color-or-theme-of-keys-dynamically-in-custom-keyboard-a
https://stackoverflow.com/questions/17714172/how-to-change-key-background-of-any-key-in-android-soft-keyboard
https://stackoverflow.com/questions/9996968/hide-android-keyboard-key-preview
https://stackoverflow.com/questions/2888896/add-words-to-androids-userdictionary