Подтвердить что ты не робот

Как показать Android-клавиатуру с режимом символов по умолчанию?

У меня есть компонент EditText, и, конечно, если вы нажмете на него, появится клавиатура Android, позволяющая пользователю вводить текст. Насколько мне известно, все программные клавиатуры для Android имеют (по крайней мере) буквенный режим (ABC) и режим символов (?123). Их представление по умолчанию - это буквенный режим.

Теперь, когда клавиатура отображается при нажатии на элемент EditText, я хочу, чтобы режим символов отображался по умолчанию. Пользователь все равно сможет переключиться на буквенный режим.

enter image description here

Есть ли способ достичь этого? Если да, то как?

4b9b3361

Ответ 1

Я публикую это, потому что я не думаю, что любой из ответов действительно затрагивает вопрос. Снимок экрана в вопросе не соответствует определенному состоянию по умолчанию InputType. Таким образом, переключение InputTypes не даст вам макет из снимка экрана.

(на основе моих исследований...)

Поддержка ввода символов не регулируется каким-либо контрактом. Очень удобно оставить символы при создании своего собственного InputMethod. ИЛИ, они могут добавить поддержку разбивки на страницы, чтобы обеспечить доступ к 100 символам. Может ли это быть связано контрактом? Может быть. Но это не в настоящее время.

Структура метода ввода не позволяет осуществлять прямую связь между клиентом и IME. Вся связь происходит либо через InputMethodManager, либо через InputConnection - односторонний канал. Однако переключение на символы с использованием ?123 является внутренним событием - не определенным состоянием/действием. Клиентские приложения не могут переключиться на него. Нет никакого публичного (или скрытого) API, чтобы это произошло.

InputType указывает на нечто совершенно иное, чем IME. Не уверен, почему все рекомендуют его использование. Вы можете, конечно, найти, что конкретный InputType предоставляет большинство необходимых ключей. Но это не то же самое, что show[ing] Android keyboard with symbols mode by default.

Возможное обходное решение:

Мы создадим пользовательский EditText. Мы не должны. Он просто сохранит все в одном месте и спасет нас от кошмара с копией.

public class CusEditText extends EditText {

    private final int mDefinedActionId;

    public CusEditText(Context context, AttributeSet attrs) {
        super(context, attrs);

        // Corresponds to 'android:imeActionId' value
        mDefinedActionId = getResources().getInteger(R.integer.definedActionId);

        setOnEditorActionListener(new OnEditorActionListener() {

            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                Log.i("CusEditText", "onEditorAction, actionId = " + actionId);

                // Only bother if (...)
                if (actionId == mDefinedActionId) {

                    // Check if current InputType is NUMBER
                    if ((getInputType() & InputType.TYPE_CLASS_NUMBER) != 0) {
                        // Toggle
                        setImeActionLabel("NUM", mDefinedActionId);
                        setInputType(InputType.TYPE_CLASS_TEXT);
                    } else {
                        // Current InputType is TEXT // Toggle
                        setImeActionLabel("ABC", mDefinedActionId);
                        setInputType(InputType.TYPE_CLASS_NUMBER);
                    }

                    // We've handled this
                    return true;
                }

                // Let someone else worry about this
                return false;
            }
        });
    }
}

Далее, нам нужно определить definedActionId. Откройте или создайте res/values/integers.xml и добавьте:

<integer name="definedActionId">-100</integer>

-100 - произвольное значение. Я проверил EditorInfo, и actionIds (IME_ACTION_XXXX) были >= 0. -100 кажется хорошим кандидатом.

В xml ваш макет будет выглядеть так:

<com.your.packagename.CusEditText
    android:layout_width="blah"
    android:layout_height="blah"
    android:inputType="number"
    android:imeActionId="@integer/definedActionId"
    android:imeActionLabel="ABC"/>

<!-- Probably use @string resource in place of ABC -->

Там нечего объяснять. IME запустится в режиме NUMBER. Вместо значка галочки он отобразит ABC. При щелчке мы перехватываем actionId и переключаем между NUMBER и TEXT. Мы используем setInputType(...), потому что он не только обновляет InputType, но также перезапускает IME с изменениями. setRawInputType(...) обновляет только InputType.

Вопросы

Как вы можете сказать, на самом деле это не решение. Если пользователь закрывает клавиатуру (используя кнопку back) в режиме ТЕКСТ, клавиатура останется в режиме ТЕКСТ, когда они снова откроют ее. Чтобы перейти в режим NUMBER, пользователю нужно нажать NUM. Кроме того, в режиме TEXT пользователь будет видеть NUM как действие вместе с опцией ?123. Это ничего не сломает, но отнимает у UX.

Мы ничего не можем сделать о ?123 в режиме ТЕКСТ по причинам, перечисленным выше. Но мы можем попытаться убедиться, что клавиатура всегда открывается в режиме NUMBER. Я расскажу о том, как мы это сделаем. Это не прямолинейно, так как мы (разработчики) не знакомы с такими событиями, как закрытие или открытие клавиатуры. Обновлено CusEditText:

public class CusEditText extends EditText {

    private final int mDefinedActionId;
    private long mLastEditorActionTime = 0L;

    public CusEditText(Context context, AttributeSet attrs) {
        super(context, attrs);

        // Corresponds to 'android:imeActionId' value
        mDefinedActionId = getResources().getInteger(R.integer.definedActionId);

        setOnEditorActionListener(new OnEditorActionListener() {

            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                Log.i("CusEditText", "onEditorAction, actionId = " + actionId);

                // Only bother if (...)
                if (actionId == mDefinedActionId) {

                    // setInputType(...) will restart the IME
                    // and call finishComposingText() 
                    // see below
                    mLastEditorActionTime = SystemClock.elapsedRealtime();

                    // Check if current InputType is NUMBER
                    if ((getInputType() & InputType.TYPE_CLASS_NUMBER) != 0) {
                        // Toggle
                        setImeActionLabel("NUM", mDefinedActionId);
                        setInputType(InputType.TYPE_CLASS_TEXT);
                    } else {
                        // Current InputType is TEXT // Toggle
                        setImeActionLabel("ABC", mDefinedActionId);
                        setInputType(InputType.TYPE_CLASS_NUMBER);
                    }

                    // We've handled this
                    return true;
                }

                // Let someone else worry about this
                return false;
            }
        });
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        InputConnection inputConnection = super.onCreateInputConnection(outAttrs);

        return new CusInputConnectionWrapper(inputConnection, false);
    }

    private class CusInputConnectionWrapper extends InputConnectionWrapper {
        private CusInputConnectionWrapper(InputConnection target, boolean mutable) {
            super(target, mutable);
        }

        @Override
        public boolean finishComposingText() {
            Log.i("CICW", "finishComposingText");

            // Ignore finishComposingText for 1 second (1000L)
            if (SystemClock.elapsedRealtime() - mLastEditorActionTime > 1000L) {
                if ((getInputType() & InputType.TYPE_CLASS_NUMBER) == 0) {
                    // InputConnection is no longer valid.
                    // Switch back to NUMBER iff required
                    setImeActionLabel("ABC", mDefinedActionId);
                    setInputType(InputType.TYPE_CLASS_NUMBER);
                }
            }

            return super.finishComposingText();
        }
    }
}

Опять же, код не требует пояснений. Мы создаем InputConnectionWrapper и слушаем обратный вызов finishComposingText(). Если мы переключаемся вручную между TEXT и NUMBER, мы используем флаг, так как finishComposingText() будет вызываться автоматически. В противном случае мы проверяем, установлен ли тип ввода на TEXT и измените его на NUMBER. Я не уверен, что finishComposingText() является правильным методом для интерпретации закрытия/открытия клавиатуры. Тестирование по API 21, vanilla android, похоже, работает. Дополнительные тесты потребуются.

Я действительно надеюсь, что кто-то может придумать лучшее, более надежное решение, чем это, или изменить мое обходное решение, чтобы оно не выглядело как.

Резюме

Задача состоит в том, чтобы обеспечить функциональность переключения между режимами ввода NUMBER и TEXT вокруг существующих двигателей входных методов (IME). Первый подход заключался в использовании imeActionLabel & imeActionId в механизме переключения. Этот подход хорошо работал с клавиатурой Google (это imeActionLabel), но не удалось с Samsung - imeActionLabel не отображается в портрете (без extract). Возможным обходным путем является включение кнопки переключения в собственный пользовательский интерфейс приложения.

Даже с клавиатурой Google буквы (текст) не отображаются, когда режим переключается на NUMBER после ввода букв. Эта проблема была исправлена ​​(по крайней мере, на тестируемых устройствах), используя флаг flagNoExtractUi, который не позволяет IME войти в полноэкранный режим в альбомной ориентации.

Окончательное решение (ожидает выполнения и тестирования)

  • IME запускается в режиме ввода NUMBER (95% случаев использования включают ввод номера)
  • Кнопка добавления в пользовательский интерфейс приложения (рядом с EditText) для переключения между режимами NUMBER и TEXT
  • Пользователь может переключаться с NUMBER на TEXT без каких-либо ограничений. Переход от TEXT к NUMBER требует, чтобы никакие алфавиты не были добавлены.
  • Тип ввода сохраняется между закрытием клавиатуры и повторным открытием. Пример. Если пользователь переключится в режим ТЕКСТ и закроет клавиатуру, он откроется в режиме ТЕКСТ. Тип InputType не reset.

Для получения дополнительной информации о проверенных подходах обратитесь к этой теме обсуждения.

Скриншоты

По умолчанию (NUMBER):

enter image description here

Переключено в TEXT:

enter image description here

Записанная ссылка на видео

Ответ 2

Я согласен, что это InputType. Если вы хотите показывать только свои номера своему пользователю, вы должны добавить к нему xml-документ для вашего текста:

        android:inputType="number"

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

        android:inputType="number|textEmailAddress"

Зайдите в http://developer.android.com/reference/android/text/InputType.html для получения дополнительных параметров. Вы также можете проверить, что показывает eclipse или андроид-студия в разделе "inputType"

Ответ 3

Я считаю, что вы хотите установить InputType вашего текста редактирования.

http://developer.android.com/reference/android/text/InputType.html

Я не уверен, что вы будете использовать, хотя вам, возможно, придется немного поиграть.

Ответ 4

Единственный способ сделать это - установить inputType вашего EditText.

Если вы хотите установить это свойство в onCreate() (или внутри пользовательского конструктора View), вы можете использовать метод setRawInputType():

mEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);

В противном случае, если вам нужно установить это свойство после onCreate() (или после пользовательского конструктора View), вы можете использовать метод setInputType():

mEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);

Очевидно, вы также можете указать свойство на уровне XML:

android:inputType="number|numberDecimal"

Вы можете играть с разными флагами, чтобы найти лучший скомпилированный фильтр.

Ответ 5

Программно можно с небольшим изменением обычного потока. Сначала вы должны установить editText как:

editText.setInputType(InputType.TYPE_CLASS_NUMBER);

Затем вам нужно прослушать keyevent. При нажатии фунта снова установите InputType на InputType.TYPE_CLASS_TEXT. Это должно работать, поскольку оно работает для меня.

editText.setOnKeyListener(new View.OnKeyListener() 
        {
         @Override
         public boolean onKey(View v, int keyCode, KeyEvent event) {
                                // TODO Auto-generated method stub
                                Log.d("KeyBoard", "Keyboard Test Key Hit");

         switch (keyCode) {
         KeyEvent.KEYCODE_POUND:
                                                                                      if(editText.setInputType(InputType.TYPE_CLASS_TEXT);
         {

         editText.setInputType(InputType.TYPE_CLASS_TEXT);
         return true;

     }

То же, что я ответил i: EditText с цифровой клавиатурой по умолчанию, но с буквенными символами