Закрыть / скрыть программную клавиатуру Android

3822

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

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

При касании за пределами клавиатуры.

Ak23
источник
13
Что делать, если у вас есть только один EditText и несколько кнопок, таких как флажки и радио? Единственное место, где вам нужна клавиатура, находится в одном EditText. Как зарегистрироваться, чтобы узнать, что что-то еще было выбрано / щелкнуто для того, чтобы скрыть клавиатуру?
АликЭльзин-килака
14
я чувствую себя глупо. Я не могу спрятать клавиатуру на ICS. Перепробовал здесь все методы и их комбинации. Ни за что. Способ показать это работает, но я не могу скрыть это независимо от того, какой токен ветра, скрыть флаги, настройки манифеста или свечи для любых святых. На показе клавиатуры я всегда вижу это: I / LatinIME (396): указан InputType.TYPE_NULL W / LatinIME (396): неожиданный класс ввода: inputType = 0x00000000 imeOptions = 0x00000000
rupps
4
/ ** * Этот метод используется для скрытия программной клавиатуры. * @param Activity * / public void hideSoftKeyboard (Activity Activity) {InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService (Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow (activity.getCurrentFocus (). getWindowToken (), 0); }
Харшал Бенаке
это сработало для меня
nmxprime
Поскольку устройства увеличивают размер и разрешение экрана, скрытие виртуальной клавиатуры становится все менее важным.
Аль-Катири Халид

Ответы:

2038

Чтобы прояснить это безумие, я хотел бы начать с извинения от имени всех пользователей Android за совершенно нелепое обращение Google с программной клавиатурой. Причина того, что на один и тот же простой вопрос так много ответов, разных, потому что этот API, как и многие другие в Android, разработан ужасно. Я не могу придумать никакого вежливого способа заявить об этом.

Я хочу спрятать клавиатуру. Я ожидаю , чтобы обеспечить Android со следующим утверждением: Keyboard.hide(). Конец. Большое спасибо. Но у Android есть проблема. Вы должны использовать, InputMethodManagerчтобы скрыть клавиатуру. Хорошо, хорошо, это API Android для клавиатуры. НО! Вы должны иметь для Contextтого, чтобы получить доступ к IMM. Теперь у нас есть проблема. Я могу захотеть скрыть клавиатуру от статического или служебного класса, который не нужен и не нужен Context. или И еще хуже, IMM требует, чтобы вы указали, что View(или даже хуже, что Window) вы хотите скрыть клавиатуру ОТ.

Это то, что делает скрытие клавиатуры таким сложным. Уважаемый Google: Когда я ищу рецепт торта, RecipeProviderна Земле нет ни одного человека , который отказался бы предоставить мне этот рецепт, если я сначала не отвечу, КТО будет съеден торт И где он будет съеден !!

Эта печальная история заканчивается ужасной правдой: чтобы спрятать клавиатуру Android, вам потребуется предоставить две формы идентификации: а Contextи а Viewили а Window.

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

public static void hideKeyboard(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    //Find the currently focused view, so we can grab the correct window token from it.
    View view = activity.getCurrentFocus();
    //If no view currently has focus, create a new one, just so we can grab a window token from it
    if (view == null) {
        view = new View(activity);
    }
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Имейте в виду, что этот служебный метод работает ТОЛЬКО при вызове из Activity! Вышеуказанные вызовы метода getCurrentFocusдля цели, Activityчтобы получить правильный маркер окна.

Но предположим, что вы хотите скрыть клавиатуру от EditTextхоста в DialogFragment? Вы не можете использовать метод выше для этого:

hideKeyboard(getActivity()); //won't work

Это не сработает, потому что вы будете передавать ссылку на Fragmentхост Activity, который не будет иметь сфокусированного контроля, пока Fragmentотображается! Вот Это Да! Итак, чтобы скрыть клавиатуру от фрагментов, я прибегаю к более низкому уровню, более распространенному и более уродливому:

public static void hideKeyboardFrom(Context context, View view) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Ниже приведена дополнительная информация, полученная из-за потраченного времени в погоне за этим решением:

О программе windowSoftInputMode

Есть еще одна точка зрения, о которой нужно знать. По умолчанию Android автоматически назначит начальный фокус первому EditTextили фокусируемому элементу управления в вашем устройстве Activity. Естественно, что InputMethod (обычно это программная клавиатура) будет реагировать на событие фокуса, показывая себя. windowSoftInputModeАтрибут AndroidManifest.xml, когда установлено stateAlwaysHidden, инструктирует клавиатуры , чтобы игнорировать это автоматически присвоенный первоначальный фокус.

<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="stateAlwaysHidden"/>

Почти невероятно, что ничего не делает для предотвращения открытия клавиатуры при прикосновении к элементу управления (если только focusable="false"и / или focusableInTouchMode="false"не назначены элементу управления). По-видимому, настройка windowSoftInputMode применяется только к событиям автоматической фокусировки, а не к событиям фокусировки, вызванным событиями касания.

Следовательно, stateAlwaysHiddenОЧЕНЬ плохо назван действительно. Возможно, это следует назвать ignoreInitialFocusвместо.

Надеюсь это поможет.


ОБНОВЛЕНИЕ: Больше способов получить жетон окна

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

Это альтернативы для приведенного выше кода. if (view == null) view = new View(activity); Они не относятся явно к вашей деятельности.

Внутри класса фрагмента:

view = getView().getRootView().getWindowToken();

Задан фрагмент fragmentв качестве параметра:

view = fragment.getView().getRootView().getWindowToken();

Начиная с вашего содержания:

view = findViewById(android.R.id.content).getRootView().getWindowToken();

ОБНОВЛЕНИЕ 2: Очистить фокус, чтобы снова не показывать клавиатуру, если вы открываете приложение из фона

Добавьте эту строку в конец метода:

view.clearFocus();

rmirabelle
источник
2
Очень хорошая рецензия. Одна вещь, однако, если вы начнете другое действие сверху, которое вызывает клавиатуру, клавиатура все равно будет присутствовать, когда вы вернетесь. Исправлено это путем удаления клавиатуры с использованием вашего метода при выходе из верхней активности.
Ойвинд
3
@rmirabelle В Fragmentкажется, что вы можете использоватьgetActivity().getWindow().getDecorView()
McX
1
Этот пост великолепен, но вам не хватает двух очень важных частей. Тонкие изменения сделаны для каждой версии и для каждого производителя. Например, на Samsung Galaxy S6 нам нужно использовать .clearFocus () перед тем, как скрыть клавиатуру ... если нет, клавиатура все равно будет всплывать при втором щелчке текста редактирования: S
Warpzit
17
Google должен просто предоставить эту Keyboard.hide();утилиту
HendraWD
1
[someView] .getContext () << Может быть к делу. Это всегда один и тот же объект. (За исключением внутренних служб ...)
Оливер Диксон
4419

Вы можете заставить Android скрыть виртуальную клавиатуру, используя InputMethodManager , вызывая hideSoftInputFromWindow, передавая токен окна, содержащего ваше сфокусированное представление.

// Check if no view has focus:
View view = this.getCurrentFocus();
if (view != null) {  
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Это заставит клавиатуру быть скрытой во всех ситуациях. В некоторых случаях вы захотите передать InputMethodManager.HIDE_IMPLICIT_ONLYвторой параметр, чтобы скрыть клавиатуру только в том случае, если пользователь явно не заставлял ее появляться (удерживая меню).

Примечание: если вы хотите сделать это в Kotlin, используйте: context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

Котлин Синтаксис

// Check if no view has focus:
 val view = this.currentFocus
 view?.let { v ->
  val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager 
  imm?.hideSoftInputFromWindow(v.windowToken, 0)
 }
Reto Meier
источник
14
Спасибо, это работает отлично, если использовать 0 в качестве второго параметра. Но если я использую InputMethodManager.HIDE_IMPLICIT_ONLY, клавиатура никогда не будет скрыта (хотя я не удерживаю меню). Есть намеки?
RoflcoptrException
27
Круто. Просто чтобы уточнить, это только отклоняет это, если присутствует, но не препятствует тому, чтобы это выскакивало, правильно?
Cheezmeister
15
Может быть полезно вызвать editText.clearFocus (), прежде чем скрывать softInput
user2224350
111
Звонок editText.clearFocus()потом InputMethodManager.HIDE_IMPLICIT_ONLYдаже работает4.1
sprocket12
11
То, что работало для меня на 4.4 / htc, выполнялось, View focused = getCurrentFocus()чтобы получить то, что определенно является в настоящее время сфокусированным представлением, вызовом focused.clearFocus()и затем inputMethodManager.hideSoftInputFromWindow(focused.getWindowToken(), 0)(с четкими флагами).
Ионокласт Бригам
806

Также полезно скрыть софт-клавиатуру:

getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
);

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

Garnet Ulrich
источник
116
Вы также можете добиться того же эффекта, добавив android: windowSoftInputMode = "stateHidden" к своей активности в манифесте.
СД
7
Попробовал это во фрагменте (ссылаясь на собственное действие) на уровне API 9, и это, к сожалению, не сработало. Пробовал вызывать его в onResume и onActivityCreated - безрезультатно.
AgentKnopf
2
Я работаю в диалоге, и это сработало. Я использую Android 3.2. Я поместил его в метод onCreateDialog (Bundle). Это не сработало в методе onCreate. Диалог диалога = super.onCreateDialog (saveInstanceState); dialog.getWindow (). setSoftInputMode (WindowManager.LayoutParams. SOFT_INPUT_STATE_ALWAYS_HIDDEN); В результате мой вид с EditTexts в нем отображается без клавиатуры. Когда пользователь касается редактируемого текста, появляется клавиатура.
Флобакка
4
Это не работает, когда фокус все еще находится в EditText (например, после нажатия кнопки). Используйте для этого решение Рето.
Нумен
4
Почему переопределение настроек манифеста - плохая идея? Я звоню из фрагмента. Там нет настройки манифеста, который применяется к фрагменту ...
Грег Эннис
349

У меня есть еще одно решение, чтобы скрыть клавиатуру:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

Здесь проходят HIDE_IMPLICIT_ONLYв положении showFlagи 0в положении hiddenFlag. Это принудительно закроет мягкую клавиатуру.

Saurabh Pareek
источник
4
Вы используете флаг скрытия в параметре showflags. Это работает только потому, что константы используют одни и те же целые числа. Пример использования правильных флагов
Алекс
протестировано на Android 4.0, мне нравится это решение, потому что у меня есть несколько текстов для редактирования, кнопки для этого действия, которые могут иметь фокус
32
@Mark: поскольку метод называется «toggleSoftInput», а не «hideSoftInput» :)
Sver
19
Это решение показывает клавиатуру, если она скрыта. Это не правильно
Михаил Катков
1
@AkashAggarwal - Это «работает», если вы игнорируете тот факт, что он работал только для вас, потому что клавиатура показывала. (Он переключает видимость клавиатуры: он скрывает, когда показывает, НО показывает, когда скрывает !!) Можете ли вы ГАРАНТИРОВАТЬ, что при любых обстоятельствах на всех устройствах для всех будущих версий Android клавиатура НЕ будет показывать в то время, когда вы звоните это? Если так, то иди и используй это!
ToolmakerSteve
149

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

tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    public void onTabChanged(String tabId) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(tabHost.getApplicationWindowToken(), 0);
    }
}
mckoss
источник
Я получил это для работы с SearchView тоже. Смотрите мой ответ ниже. Спасибо, МакКосс!
Azurespot
139

Пожалуйста, попробуйте этот код ниже onCreate()

EditText edtView=(EditText)findViewById(R.id.editTextConvertValue);
edtView.setInputType(0);
Jeyavel
источник
2
Этот метод работает как средство для устранения ошибки «не скрыть программную клавиатуру» в 2.0 и 2.1, как описано в code.google.com/p/android/issues/detail?id=7115 ... метод hideSoftInputFromWindow перечисленные выше не работали, когда я пытался это сделать, но editView.setInputType (0) делал.
Спайк Уильямс
18
Это допустимо для Javadoc (не хак), хотя я бы переписал этот метод какeditView.setInputType(InputType.TYPE_NULL);
Bostone 11.10.10
3
это работает, однако, он скрывает Android: подсказка. Я использую Android 1.5
Tirtha
это отлично подходит для случаев, когда вам нужно закрыть клавиатуру из диалогового окна, не нужно получать экземпляр или что-либо еще и можно назначить это для всех редактируемых текстов, когда пользователь нажимает кнопку, закрывающую диалог
I'm_With_Stupid
Это работает, но это также скрывает курсор. Мне нужен курсор, но нет системной клавиатуры.
Стефан Брендл
129

Обновление: я не знаю, почему это решение больше не работает (я только что протестировал на Android 23). Пожалуйста, используйте вместо этого решение Saurabh Pareek . Вот:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
//Hide:
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
//Show
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

Старый ответ:

//Show soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//hide keyboard :
 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Нгуен Минь Бинь
источник
8
Где я должен разместить этот код? Я пытался вставить getWindow (). SetSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); в onCreate (), но клавиатура никогда не скрывается
user2236096
не работает, протестировано в radioGroup.setOnCheckedChangeListener, API 23
Кристиан Шефер,
Если вы посмотрите ближе, InputMethodManager.HIDE_IMPLICIT_ONLY и InputMethodManager.SHOW_IMPLICIT имеют одинаковое значение, равное «1», поэтому между этими вызовами нет разницы. => не работает
Palejandro
если вызывается imm.toggleSoftInput (InputMethodManager.HIDE_IMPLICIT_ONLY, 0); тогда клавиатура будет отображаться на экране :) Лучшая реализация: github.com/ravindu1024/android-keyboardlistener Shame на Android SDK
Duna
I don't know why this solution is not work any more- потому что это Android , все сможет измениться, возможно, отчасти из-за плохого дизайна ... Мы пишем небрежно, затем вычеркиваем все и переписываем все.
Король Король
89
protected void hideSoftKeyboard(EditText input) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}
Sreedev R
источник
5
Это сработало для меня! Но почему вы положили input.setInputType (0) ? Я не мог взаимодействовать с EditTextView, когда у меня была эта строка кода (она работала, когда я ее удалял).
ymerdrengene
Наверное input.getContext().getSystemService(Context.INPUT_METHOD_SERVICE).
CoolMind
Я удалил input.setInputType(0);из этого кода. Это изменило поведение клавиатуры и inputTypeдля EditText.
CoolMind
74

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

Создайте функцию, которая будет управлять некоторыми из EditTextсвойств:

public void setEditTextFocus(boolean isFocused) {
    searchEditText.setCursorVisible(isFocused);
    searchEditText.setFocusable(isFocused);
    searchEditText.setFocusableInTouchMode(isFocused);

    if (isFocused) {
        searchEditText.requestFocus();
    }
}

Затем убедитесь, что на Focus EditTextвы открываете / закрываете клавиатуру:

searchEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (v == searchEditText) {
            if (hasFocus) {
                // Open keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(searchEditText, InputMethodManager.SHOW_FORCED);
            } else {
                // Close keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(searchEditText.getWindowToken(), 0);
            }
        }
    }
});

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

setEditTextFocus(true);

И для закрытия звонка:

setEditTextFocus(false);
Rotemmiz
источник
+1 - если вы хотите начать действие с закрытой клавиатурой, используйте это решение и добавьте onclicklistener, который устанавливает setEditTextFocus (true). Работает как шарм!
Шлингель
Я получил «Не удается разрешить контекст символа» в 7-й и 10-й строке второго блока кода.
Дай мне
Вместо этого используйте getContext ()
Rotemmiz
61

Пока у Саураба Парика лучший ответ.

Можно использовать и правильные флаги.

/* hide keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

/* show keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

Пример реального использования

/* click button */
public void onClick(View view) {      
  /* hide keyboard */
  ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
      .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

  /* start loader to check parameters ... */
}

/* loader finished */
public void onLoadFinished(Loader<Object> loader, Object data) {
    /* parameters not valid ... */

    /* show keyboard */
    ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
        .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

    /* parameters valid ... */
}
Алекс
источник
1
Это самый эффективный вариант для последней версии. Всегда нужно настроить его для более старых версий. Особенно до v3.
Алекс
2
@Mazen: использоватьfragment.getActivity().getSystemService();
Йохан S
Это наиболее полный ответ, охватывающий как шоу, так и скрытие.
Андре Штальц
4
Нет. На моем Samsung Tab, Android 5.0, так называемый код «скрыть клавиатуру» выше переключит программную клавиатуру - если она уже скрыта, она покажет ее. Есть причина, по которой эта функция имеет TOGGLE в названии.
ToolmakerSteve
57

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

// 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);
shontauro
источник
Единственный, который работал для меня на Motorola с Android 5.1
GMX
55

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

В вашем 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. Просто посмотрите, как ведет себя команда EditTextwith android:imeOptions="actionDone", вы хотите добиться того же поведения тем же способом.


Проверьте этот связанный ответ

оборота Alex.F
источник
Это ответ. Единственный метод, который работает кросс-версия. Я вернулся к этому вопросу, чтобы опубликовать этот ответ, потому что я не думал, что кто-то еще знал
Ноа Пассалаква
Это должен быть правильный ответ. Вместо того, чтобы обманывать Android, чтобы скрыть клавиатуру, когда она действительно должна быть там, мы говорим ему, что пользователь завершил, что, в свою очередь, вызывает ту же ImeAction [глупое имя, я признаю], как если бы пользователь нажал «DONE» на клавиатуре , Таким образом, не имеет значения, если пользователь подтверждает ввод с клавиатуры или нажимает кнопку пользовательского интерфейса.
Оливер Хауслер
46

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

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);
оборота
источник
Сработало частично, даже если клавиатура была скрыта, isActive () возвращает false!
xpto
Конечно, это так и должно быть. Или, может быть, я вас не понимаю. Во всяком случае, вы могли бы дополнить класс с hide()и show()методами , чтобы иметь больше контроля над тем, когда он должен показать , а когда нет. У меня работает, я тоже это сделал :) Пример редактирования
slinden77
@YoushaAleayoub да, будет. KeyBoard.toggle(fragment.getActivity())
slinden77
@ slinden77, лол, я говорю о твоем ответе ... не тот, который ты прокомментировал. Так что ответ по-прежнему не будет работать.
Юша Алеауб
@YoushaAleayoub хм да, будет. Оригинальный вопрос не упоминает фрагменты, вы тот, кто упомянул фрагменты. Так что мой ответ совершенно верный. Чтобы использовать его с фрагментами, вызывайте метод не так Fragment, как в комментариях. Узнайте, как использовать методы, пожалуйста, а затем вернуться. Ты путаешь людей со своими глупыми ответами
slinden77
43

Я использую пользовательскую клавиатуру для ввода шестнадцатеричного числа, поэтому я не могу показать клавиатуру 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
    }
}

Для более старых версий я получил очень хорошие (но далеко не идеальные) результаты с a OnGlobalLayoutListener, добавленным с помощью a 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);
sergio91pt
источник
Спасибо. Два флага FLAG_ALT_FOCUSABLE_IM и FLAG_ALT_FOCUSABLE_IM - фактически единственное, что помогло в моем случае. Я не хотел, чтобы в моей деятельности отображалась клавиатура - даже когда пользователь нажимал текст редактирования. (Я сделал свою собственную "клавиатуру").
Даниил Новак,
Классное решение, однако, если ваша передняя активность не полноэкранная, клавиатура видна за ней. Также вспомогательное средство перемещения курсора клавиатуры также все еще видимо. И это не скины.
Halxinate
Я второй это. Из всех возможных способов работает только метод getWindow (). SetFlags (), по крайней мере, на стоковой Android 5.1. Обратите внимание, что setSoftInputShownOnFocus () теперь является setShowSoftInputOnFocus () и больше не скрыт, но не работает, по крайней мере, когда пользователь касается поля.
olefevre
Ваше «обновление» было единственным рабочим решением для меня. Я ищу решение по крайней мере два часа :)
Стефан Брендл
33
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);
    }
}
shobhan
источник
30

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

Вы можете увидеть рабочую реализацию этого в моем приложении чистой 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 () и вернуться на домашний экран устройства.

Luke Sleeman
источник
1
сложный обходной путь, но я думаю, что это слишком много, чтобы воссоздать тысячи объектов, просто чтобы скрыть клавиатуру. Я не знаю, кто разработал IMM для Android, но он пахнет как Windows APi. На мой взгляд, хороший IME должен иметь два метода: скрыть и показать :-)
rupps
Это все правда, но мой обходной путь имеет одно преимущество - он всегда работает! Я не мог найти другого решения, которое бы всегда переключало клавиатуру, независимо от того, какие поля в пользовательском интерфейсе имеют фокус, что пользователь сделал для переключения и клавиатуры и какую версию андроида они запускают: - \
Люк Слиман
Чувак, я отчаянно пытаюсь спрятать клавиатуру. Перепробовал тысячи вещей и оооочень работает. Но ваш обходной путь для меня слишком большой, мне нужно воссоздать, как 10 фрагментов, инициализировать сервисы, удалить множество WeakReferences .... вы знаете? GC просто выбросил бы как 25mb: S ... Все еще ищу надежный способ сделать это :(
rupps
@Dmitry ну это не привет мир ... это сложное приложение для планшетов. Я отказываюсь полностью выгружать его из памяти, просто чтобы спрятать глупую клавиатуру ... В любом случае я нашел что-то, что работает, сочетая тысячу предложенных здесь решений :)
rupps
27

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

if (getCurrentFocus() != null) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
Saran
источник
25

Благодаря такому ответу я получил следующее, что в моем случае прекрасно работает при прокрутке фрагментов 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);
    }
}
бана-геоинженерия
источник
21

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

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();
}
Ash
источник
18

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

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

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

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

Петр Айтай
источник
16

Вот как вы делаете это в Mono для Android (AKA MonoDroid)

InputMethodManager imm = GetSystemService (Context.InputMethodService) as InputMethodManager;
if (imm != null)
    imm.HideSoftInputFromWindow (searchbox.WindowToken , 0);
Ян Винк
источник
1
Что находится searchboxво фрагменте?
PCoder
16

Это сработало для меня из-за странного поведения клавиатуры

private boolean isKeyboardVisible() {
    Rect r = new Rect();
    //r will be populated with the coordinates of your view that area still visible.
    mRootView.getWindowVisibleDisplayFrame(r);

    int heightDiff = mRootView.getRootView().getHeight() - (r.bottom - r.top);
    return heightDiff > 100; // if more than 100 pixels, its probably a keyboard...
}

protected void showKeyboard() {
    if (isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if (getCurrentFocus() == null) {
        inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    } else {
        View view = getCurrentFocus();
        inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_FORCED);
    }
}

protected void hideKeyboard() {
    if (!isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    View view = getCurrentFocus();
    if (view == null) {
        if (inputMethodManager.isAcceptingText())
            inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
    } else {
        if (view instanceof EditText)
            ((EditText) view).setText(((EditText) view).getText().toString()); // reset edit text bug on some keyboards bug
        inputMethodManager.hideSoftInputFromInputMethod(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}
Pinhassi
источник
1
Думаю, я попробовал 10 ответов до этого. Оставил надежду. Спасибо чувак.
Боллинг
Что такое mRootView?
justdan0227
14

Добавьте к своей деятельности android:windowSoftInputMode="stateHidden"в файле манифеста. Пример:

<activity
            android:name=".ui.activity.MainActivity"
            android:label="@string/mainactivity"
            android:windowSoftInputMode="stateHidden"/>
NickUnuchek
источник
14

Простой и легкий в использовании метод, просто вызовите hideKeyboardFrom (YourActivity.this); прятать клавиатуру

/**
 * This method is used to hide keyboard
 * @param activity
 */
public static void hideKeyboardFrom(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
Навид Ахмад
источник
13

Просто используйте этот оптимизированный код в своей деятельности:

if (this.getCurrentFocus() != null) {
    InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
    inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
Hamid FzM
источник
Работает отлично. Спасибо
Алиф
12
public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

после этого вызовите onTouchListener:

findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Utils.hideSoftKeyboard(activity);
        return false;
    }
});
Сагар Майяд
источник
Попробуйте также - это сработало для меня: InputMethodManager imm = ((InputMethodManager) getSystemService (Activity.INPUT_METHOD_SERVICE)); imm.hideSoftInputFromWindow (getWindow (). getCurrentFocus (). getWindowToken (), 0);
Zmicer
12

использовать этот

this.getWindow().setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Атиш Агравал
источник
12

Для моего случая я использовал SearchView на панели действий. После того, как пользователь выполнит поиск, клавиатура снова откроется.

Использование InputMethodManager не закрывало клавиатуру. Мне пришлось очистить фокус и установить фокусировку в поиске на false:

mSearchView.clearFocus();
mSearchView.setFocusable(false);
Tommy Chheng
источник
1
Очень умный. Если пользователь хочет другой поиск, просто нажмите поиск еще раз.
Алекс
SearchView не имеет clearFocus()на страницах API Android, так что это не сработало для меня, но другое решение было (см. Мой ответ ниже).
Azurespot
@Noni A, stackoverflow.com/questions/7409288/…
Юша Алеауб
12

У меня есть случай, когда мой EditTextможет быть расположен также в AlertDialog, так что клавиатура должна быть закрыта при отклонении. Следующий код, кажется, работает где угодно:

public static void hideKeyboard( Activity activity ) {
    InputMethodManager imm = (InputMethodManager)activity.getSystemService( Context.INPUT_METHOD_SERVICE );
    View f = activity.getCurrentFocus();
    if( null != f && null != f.getWindowToken() && EditText.class.isAssignableFrom( f.getClass() ) )
        imm.hideSoftInputFromWindow( f.getWindowToken(), 0 );
    else 
        activity.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN );
}
injecteer
источник
1
Это решение лучше, поскольку вам не нужно контролировать, какой EditText передается в качестве параметра методу hideSoftInputFromWindow (). Отлично работает !!
Billyjoker
12

Я почти перепробовал все эти ответы, у меня были некоторые случайные проблемы, особенно с Samsung Galaxy S5.

В итоге я заставляю себя показывать и прятаться, и это прекрасно работает:

/**
 * Force show softKeyboard.
 */
public static void forceShow(@NonNull Context context) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}

/**
 * Force hide softKeyboard.
 */
public static void forceHide(@NonNull Activity activity, @NonNull EditText editText) {
    if (activity.getCurrentFocus() == null || !(activity.getCurrentFocus() instanceof EditText)) {
        editText.requestFocus();
    }
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
    activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}
ahmed_khan_89
источник