Пользовательская клавиатура: обработка изменения вводаType

Я сталкиваюсь с проблемой, которую я не могу понять. Я написал простую пользовательскую клавиатуру IME на основе этого образца.

В основном это две пользовательские клавиатуры, одна для букв и одна для цифр. Они используют разные макеты.

Однако, когда я добавляю два элемента управления EditText один для текста и один для чисел, клавиатура не обновляется до того типа, который ему принадлежит. Я имею в виду, что если я inputType="text" EditText с inputType="text" , появится раскладка клавиатуры QWERTY. Но затем, когда я выбираю второй EditText с inputType="number" клавиатура QWERTY снова появляется. Однако предполагается, что загружается другой макет для чисел, которые подключены к коду.

Другими словами, вот макет тестовой активности:

Введите описание изображения здесь

Теперь, если я выберу поле «Текст», клавиатура QWERTY будет выглядеть следующим образом:

Введите описание изображения здесь

Тем не менее, если я выберу «Поданное количество», клавиатура QWERTY все еще отображается, что неправильно.

Введите описание изображения здесь

Ожидаемое поведение этой клавиатуры будет отображаться.

Введите описание изображения здесь

Вот код для CustomIME, и я попытался использовать postInvalidate() в представлении, предварительно onInitializeInterface() все макеты во время onInitializeInterface() но ничего не onInitializeInterface() . Он никогда не переключается на макет номера правильно

 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); } } } 

И макеты:

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> 

Наконец, раскладки клавиатуры ( custom_ime_qwerty.xml и 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" /> 

Solutions Collecting From Web of "Пользовательская клавиатура: обработка изменения вводаType"

Я думаю, что onStartInputView() – это обратный вызов, который вам нужно получить:

Вызывается, когда отображается представление ввода, и ввод начинается в новом редакторе. Это всегда будет вызываться после onStartInput (EditorInfo, boolean) , что позволяет вам выполнять свою общую настройку и настраивать только настройки для просмотра. Вам гарантировано, что onCreateInputView () будет вызываться некоторое время до вызова этой функции.

Итак, вы узнаете, какой именно тип ввода должен отображаться в onStartInput() , но фактическое место для переключения на этот новый тип клавиатуры должно быть onStartInputView() .

Посмотрите, как пример приложения SoftKeyboard обрабатывает эту функциональность.

@Override public void onStartInput(EditorInfo attribute, boolean restarting) { super.onStartInput(attribute, restarting); ... // We are now going to initialize our state based on the type of // text being edited. switch (attribute.inputType & InputType.TYPE_MASK_CLASS) { case InputType.TYPE_CLASS_NUMBER: case InputType.TYPE_CLASS_DATETIME: mCurKeyboard = mSymbolsKeyboard; break; case InputType.TYPE_CLASS_PHONE: mCurKeyboard = mSymbolsKeyboard; break; case InputType.TYPE_CLASS_TEXT: mCurKeyboard = mQwertyKeyboard; ... break; default: // For all unknown input types, default to the alphabetic // keyboard with no special features. mCurKeyboard = mQwertyKeyboard; } } @Override public void onStartInputView(EditorInfo attribute, boolean restarting) { super.onStartInputView(attribute, restarting); // Apply the selected keyboard to the input view. setLatinKeyboard(mCurKeyboard); ... } private void setLatinKeyboard(LatinKeyboard nextKeyboard) { final boolean shouldSupportLanguageSwitchKey = mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken()); nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey); mInputView.setKeyboard(nextKeyboard); }
@Override public void onStartInput(EditorInfo attribute, boolean restarting) { super.onStartInput(attribute, restarting); ... // We are now going to initialize our state based on the type of // text being edited. switch (attribute.inputType & InputType.TYPE_MASK_CLASS) { case InputType.TYPE_CLASS_NUMBER: case InputType.TYPE_CLASS_DATETIME: mCurKeyboard = mSymbolsKeyboard; break; case InputType.TYPE_CLASS_PHONE: mCurKeyboard = mSymbolsKeyboard; break; case InputType.TYPE_CLASS_TEXT: mCurKeyboard = mQwertyKeyboard; ... break; default: // For all unknown input types, default to the alphabetic // keyboard with no special features. mCurKeyboard = mQwertyKeyboard; } } @Override public void onStartInputView(EditorInfo attribute, boolean restarting) { super.onStartInputView(attribute, restarting); // Apply the selected keyboard to the input view. setLatinKeyboard(mCurKeyboard); ... } private void setLatinKeyboard(LatinKeyboard nextKeyboard) { final boolean shouldSupportLanguageSwitchKey = mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken()); nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey); mInputView.setKeyboard(nextKeyboard); }