Закрыть / скрыть программную клавиатуру Android - PullRequest
3500 голосов
/ 10 июля 2009

У меня есть EditText и Button в моем макете.

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

Ответы [ 92 ]

52 голосов
/ 22 февраля 2012

от такого поиска, здесь я нашел ответ, который работает для меня

// Show soft-keyboard:
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

// Hide soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
49 голосов
/ 04 августа 2014

Краткий ответ

В вашем OnClick слушателе вызовите onEditorAction из EditText с IME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        someEditText.onEditorAction(EditorInfo.IME_ACTION_DONE)
    }
});

Развертка

Мне кажется, что этот метод лучше, проще и более соответствует шаблону дизайна Android. В приведенном выше простом примере (и, как правило, в большинстве распространенных случаев) у вас будет EditText, который имеет / имел фокус, и он также обычно был тем, который вызывал клавиатуру в первую очередь (он определенно способен вызвать это во многих распространенных сценариях). Таким же образом, это должен быть тот, кто отпустит клавиатуру, обычно это может быть сделано с помощью ImeAction. Просто посмотрите, как ведет себя EditText с android:imeOptions="actionDone", вы хотите добиться того же поведения тем же способом.


Отметьте связанный ответ

44 голосов
/ 07 сентября 2013

Это должно работать:

public class KeyBoard {

    public static void show(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY); // show
    }

    public static void hide(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); // hide
    }

    public static void toggle(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        if (imm.isActive()){
            hide(activity); 
        } else {
            show(activity); 
        }
    }
}

KeyBoard.toggle(activity);
40 голосов
/ 04 мая 2012

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

В v3.2.4_r1 setSoftInputShownOnFocus(boolean show) был добавлен, чтобы контролировать погоду или не отображать клавиатуру, когда TextView получает фокус, но он все еще скрыт, поэтому необходимо использовать отражение:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
    try {
        Method method = TextView.class.getMethod("setSoftInputShownOnFocus", boolean.class);
        method.invoke(mEditText, false);
    } catch (Exception e) {
        // Fallback to the second method
    }
}

Для более старых версий я получил очень хорошие результаты (но далеко не идеальные) с OnGlobalLayoutListener, добавленным с помощью ViewTreeObserver из моего корневого представления, а затем проверяя, отображается ли клавиатура следующим образом:

@Override
public void onGlobalLayout() {
    Configuration config = getResources().getConfiguration();

    // Dont allow the default keyboard to show up
    if (config.keyboardHidden != Configuration.KEYBOARDHIDDEN_YES) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
    }
}

Это последнее решение может показывать клавиатуру в течение доли секунды и портить ручки выбора.

Когда в клавиатуре появляется полный экран, onGlobalLayout не вызывается. Чтобы избежать этого, используйте TextView # setImeOptions (int) или в объявлении TextView XML:

android:imeOptions="actionNone|actionUnspecified|flagNoFullscreen|flagNoExtractUi"

Обновление: Только что нашел, какие диалоги используются, чтобы никогда не показывать клавиатуру и работает во всех версиях:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
        WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
31 голосов
/ 01 июня 2015
public void setKeyboardVisibility(boolean show) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if(show){
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    }else{
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
    }
}
28 голосов
/ 06 апреля 2013

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

Вы можете увидеть рабочую реализацию этого в моем приложении clean RPN .

После тестирования многих из предложенных ответов на различных телефонах (включая устройства froyo и пряники) стало очевидно, что приложения для Android могут надежно:

  1. Временно скрыть клавиатуру. Он появится снова, когда пользователь фокусирует новое текстовое поле.
  2. Показать клавиатуру, когда начинается действие и установите флаг на активность, указывающую, что они должны клавиатура всегда быть видимым Этот флаг может быть установлен только тогда, когда активность инициализируется.
  3. Отметьте деятельность, чтобы никогда не показывать или не разрешать использование клавиатура. Этот флаг может быть установлен только тогда, когда активность инициализируется.

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

К сожалению, пункты 2 и 3 в списке обеспечивают надежность работы только при запуске операции. После того, как действие стало видимым, вы не сможете надолго скрыть или показать клавиатуру Хитрость заключается в том, чтобы фактически возобновить свою деятельность, когда пользователь нажимает кнопку переключения клавиатуры. В моем приложении, когда пользователь нажимает кнопку переключения клавиатуры, запускается следующий код:

private void toggleKeyboard(){

    if(keypadPager.getVisibility() == View.VISIBLE){
        Intent i = new Intent(this, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        Bundle state = new Bundle();
        onSaveInstanceState(state);
        state.putBoolean(SHOW_KEYBOARD, true);
        i.putExtras(state);

        startActivity(i);
    }
    else{
        Intent i = new Intent(this, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        Bundle state = new Bundle();
        onSaveInstanceState(state);
        state.putBoolean(SHOW_KEYBOARD, false);
        i.putExtras(state);

        startActivity(i);
    }
}

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

Внутри метода onCreate запускается следующий код:

if(bundle.getBoolean(SHOW_KEYBOARD)){
    ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(newEquationText,0);
    getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
else{
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
            WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}

Если должна отображаться программная клавиатура, то InputMethodManager должен показать клавиатуру, а в окне указывается, чтобы программный ввод был всегда видимым. Если программная клавиатура должна быть скрыта, то устанавливается WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM.

Этот подход надежно работает на всех устройствах, на которых я тестировал - от 4-летнего телефона HTC с Android 2.2 до Nexus 7 с 4.2.2. Единственный недостаток этого подхода - вы должны быть осторожны при обращении с кнопкой «назад». Поскольку мое приложение имеет только один экран (калькулятор), я могу переопределить onBackPressed () и вернуться на главный экран устройства.

25 голосов
/ 05 сентября 2013

В качестве альтернативы это универсальное решение , если вы хотите закрыть программную клавиатуру из любого места без ссылки на поле (EditText), которое использовалось для открытия клавиатуры, но все же хотел сделать это, если поле было сфокусировано, вы можете использовать это (из Activity):

if (getCurrentFocus() != null) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
23 голосов
/ 23 июля 2015

Благодаря этому SO-ответу я получил следующее, которое в моем случае хорошо работает при прокрутке фрагментов ViewPager ...

private void hideKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

private void showKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
    }
}
20 голосов
/ 14 сентября 2012

Приведенные выше ответы работают для разных сценариев, но Если вы хотите спрятать клавиатуру внутри представления и изо всех сил пытаетесь получить правильный контекст, попробуйте следующее:

setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        hideSoftKeyBoardOnTabClicked(v);
    }
}

private void hideSoftKeyBoardOnTabClicked(View v) {
    if (v != null && context != null) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

и получить контекст, получить его из конструктора :)

public View/RelativeLayout/so and so (Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.context = context;
    init();
}
18 голосов
/ 13 декабря 2011

Если вы хотите закрыть экранную клавиатуру во время модульного или функционального теста, вы можете сделать это, нажав кнопку «Назад» в вашем тесте:

// Close the soft keyboard from a Test
getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);

Я поставил «кнопку назад» в кавычки, так как выше не вызывает onBackPressed() для рассматриваемой деятельности. Просто закрывает клавиатуру.

Обязательно сделайте небольшую паузу, прежде чем двигаться дальше, поскольку для закрытия кнопки «назад» требуется некоторое время, поэтому последующие нажатия кнопки «Виды» и т. Д. Не будут регистрироваться до тех пор, пока не произойдет короткая пауза (1 секунда достаточно долго)

...