Custom Keyboard: handling inputType change

Viewed 4150

I am running into an issue that I can't figure out. I wrote a simple custom IME keyboard based on this sample.

It basically has two custom keyboards, one for letters and one for numbers. They use different layouts.

However, when I add two EditText controls one for text and one for numbers, the keyboard does not refresh to the type it belongs. What I mean is that if I select the EditText with inputType="text" first, the QWERTY keyboard layout comes up. But then when I select the second EditText with inputType="number" the QWERTY keyboard shows up again. However it is supposed to load a different layout for numbers that is wired into the code.

In other words, here's the test activity layout:

enter image description here

Now if I select the "Text" field, the QWERTY keyboard comes up as below:

enter image description here

However, if I select the "Number" filed, the QWERTY keyboard still shows up which is wrong.

enter image description here

The expected behavior would be this keyboard to show up.

enter image description here

Here's the code for the CustomIME and I tried to use postInvalidate() on the view, pre-load all layouts during onInitializeInterface() but nothing worked. It never switches to the number's layout properly

public class CustomIME extends InputMethodService
        implements KeyboardView.OnKeyboardActionListener {

    public static final String CUSTOM_IME = "CUSTOM_IME";
    private KeyboardView mKeyboardView;
    private Keyboard mKeyboardCurrent;
    private KeyboardType mKeyboardTypeCurrent = KeyboardType.QWERTY_LETTERS;
    private boolean mCAPs = false;


    enum KeyboardType {
        QWERTY_LETTERS,
        NUMBERS
    }

    @Override
    public View onCreateInputView() {
        loadCurrentKeyboard();
        mKeyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.custom_ime_keyboard, null);
        mKeyboardView.setBackgroundResource(R.drawable.btn_gradient);
        mKeyboardView.setOnKeyboardActionListener(this);

        if (mKeyboardCurrent != null) {
            mKeyboardView.setKeyboard(mKeyboardCurrent);
        }

        return mKeyboardView;
    }

    @Override
    public void onInitializeInterface() {
        // tried loading everything here but did not make a difference
    }

    private void loadCurrentKeyboard() {
        if (mKeyboardTypeCurrent == KeyboardType.QWERTY_LETTERS) {
            mKeyboardCurrent = new Keyboard(getApplicationContext(), R.xml.custom_ime_qwerty);
        } else if (mKeyboardTypeCurrent == KeyboardType.NUMBERS) {
            mKeyboardCurrent = new Keyboard(getApplicationContext(), R.xml.custom_ime_number);
        } else {
            Log.e(CUSTOM_IME, "Invalid keyboard type");
        }
    }

    @Override
    public void onStartInput(EditorInfo attribute, boolean restarting) {
        super.onStartInput(attribute, restarting);
        switch (attribute.inputType & InputType.TYPE_MASK_CLASS) {
            case InputType.TYPE_CLASS_NUMBER:
                boolean signed = (attribute.inputType & InputType.TYPE_NUMBER_FLAG_SIGNED) != 0;
                boolean decimal = (attribute.inputType & InputType.TYPE_NUMBER_FLAG_DECIMAL) != 0;

                // set default
                mKeyboardTypeCurrent = KeyboardType.QWERTY_LETTERS;
                if (!signed && !decimal) {
                    mKeyboardTypeCurrent = KeyboardType.NUMBERS;
                }
                break;
            case InputType.TYPE_CLASS_TEXT:
            default:
                mKeyboardTypeCurrent = KeyboardType.QWERTY_LETTERS;
        }

        // This did not make a difference
        if (mKeyboardView != null) {
            mKeyboardView.postInvalidate();
        }
    }

    @Override
    public void onKey(int primaryCode, int[] keyCodes) {
        InputConnection inputConnection = getCurrentInputConnection();
        switch (primaryCode) {
            default:
                char asciiCode = (char) primaryCode;
                if (Character.isLetter(asciiCode) && mCAPs) {
                    asciiCode = Character.toUpperCase(asciiCode);
                }
                inputConnection.commitText(String.valueOf(asciiCode), 1);
        }
    }
}

And the layouts:

custom_ime_keyboard.xml:

<?xml version="1.0" encoding="UTF-8"?>
<android.inputmethodservice.KeyboardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/custom_ime_keyboard_id1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:keyPreviewLayout="@layout/custom_ime_preview" />

activity_main.xml

<LinearLayout
    android:id="@+id/layout1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_margin="10dp"
    android:orientation="horizontal">

    <EditText
        android:id="@+id/edit1"
        android:layout_width="100dp"
        android:layout_height="60dp"
        android:inputType="text"
        android:hint="Text"
        android:padding="10dp"
        android:textSize="12sp" />

    <EditText
        android:id="@+id/edit2"
        android:layout_width="100dp"
        android:layout_height="60dp"
        android:hint="Number"
        android:inputType="number"
        android:padding="10dp"
        android:textSize="12sp" />
</LinearLayout>

Finally the keyboard layouts (custom_ime_qwerty.xml, and custom_ime_number.xml).

<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyHeight="64dp"
    android:keyWidth="9%p">
    <!--1st row-->
    <Row android:rowEdgeFlags="top">
        <Key
            android:codes="113"
            android:keyEdgeFlags="left"
            android:keyLabel="q" />
        <Key
            android:codes="119"
            android:keyLabel="w" />
        <Key
            android:codes="101"
            android:keyLabel="e" />
        <Key
            android:codes="114"
            android:keyLabel="r" />
        etc...


<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyHeight="64dp"
    android:keyWidth="20%p"
    android:label="number"
    android:verticalGap="0px">
    <!--1st row-->
    <Row android:rowEdgeFlags="top">
        <Key
            android:codes="49"
            android:keyEdgeFlags="left"
            android:keyLabel="1" />
        <Key
            android:codes="50"
            android:keyLabel="2" />
        <Key
            android:codes="51"
            android:keyLabel="3" />
1 Answers
Related