Закрийте / прихойте програмну клавіатуру для Android


3818

У мене є EditTextі Buttonв моєму макеті.

Записавшись у поле редагування та натиснувши на Button, я хочу приховати віртуальну клавіатуру. Я припускаю, що це простий фрагмент коду, але де я можу знайти його приклад?

При дотику за межі клавіатури.


13
Що робити, якщо у вас є лише один EditText і кілька кнопок, як-от прапорці та радіостанції? Єдине потрібне вам клавіатура - це єдиний EditText. Як зареєструватися, щоб знати, що щось інше було обрано / натиснене для того, щоб приховати клавіатуру?
AlikElzin-kilaka

14
я почуваюся дурним. Я не можу приховати клавіатуру на ICS. Випробували тут всі методи та їх комбінації. У жодному разі. Метод його показу працює, але я не можу його приховати незалежно від того, який жетон вітрів, приховати прапори, налаштування маніфесту чи свічки будь-яким святим. На показі клавіатури я завжди бачу це: I / LatinIME (396): InputType.TYPE_NULL вказано W / LatinIME (396): Неочікуваний вхідний клас: inputType = 0x00000000 imeOptions = 0x00000000
rupps

4
/ ** * Цей метод використовується для приховування м'якої клавіатури. * @param Activity * / public void hidSoftKeyboard (Activity Activity) {InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService (Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow (activity.getCurrentFocus (). getWindowToken (), 0); }
Харшал Бенеке

це працювало для мене
nmxprime

З збільшенням розміру та роздільної здатності екрану приховування віртуальної клавіатури стає менш важливим.
Аль-Катірі Халід

Відповіді:


2033

Щоб допомогти роз’яснити це безумство, я хотів би почати з вибачення від імені всіх користувачів Android за відверто смішне поводження Google з м'якою клавіатурою. Причина, що існує так багато відповідей, кожен відрізняється, на той самий простий питання, тому що цей API, як і багато інших в Android, жахливо розроблений. Я не можу придумати жодного ввічливого способу заявити про це.

Я хочу приховати клавіатуру. Я очікую , щоб забезпечити Android з наступним твердженням: Keyboard.hide(). Кінець. Дуже дякую. Але в Android є проблема. Ви повинні використовувати клавішу " InputMethodManagerприховати" клавіатуру. Гаразд, чудово, це API для клавіатури Android. АЛЕ! Вам потрібно мати Contextдоступ, щоб отримати доступ до IMM. Зараз у нас є проблема. Можливо, я захочу сховати клавіатуру від статичного чи утилітного класу, який не має жодної користі та потреби Context. або І чим гірше, IMM вимагає вказати, що View(або ще гірше, що Window) ви хочете приховати від клавіатури ВІД.

Саме це робить приховування клавіатури настільки складним. Шановний Google: Коли я шукаю рецепт торта, RecipeProviderна Землі немає жодного, який би відмовився надати мені рецепт, якщо я вперше не відповіду, КОМО торт буде з'їдений І де він буде з'їдений !!

Ця сумна історія закінчується потворною правдою: щоб сховати клавіатуру Android, вам потрібно буде надати 2 форми ідентифікації: a Contextі або a, Viewабо a 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();


2
Дуже приємний запис. Однак одне, якщо ви почнете іншу діяльність поверх неї, яка запускає клавіатуру, клавіатура все одно буде присутня при поверненні. Виправлено це, видаливши клавіатуру за допомогою вашого методу, коли виходили з найвищої активності.
Ойвінд

3
@rmirabelle FragmentЗдається, ви можете скористатисяgetActivity().getWindow().getDecorView()
McX

1
Ця публікація чудова, але вам не вистачає двох дуже важливих складових. Тонкі зміни, зроблені за версію та зроблені за виробництво. Наприклад, для галактики Samsung s6 нам потрібно використовувати .clearFocus () перед тим, як приховати клавіатуру ... якщо не клавіатура, то все-таки з'явиться другий клік редагування: S
Warpzit

17
Google повинен просто реально надати цю Keyboard.hide();утиліту
HendraWD

1
[someView] .getContext () << Дія може бути залежною від діяльності. Це завжди той самий об’єкт. (За винятком внутрішніх служб ...)
Олівер Діксон,

4417

Ви можете змусити 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як другий параметр, щоб переконатися, що ви приховуєте клавіатуру лише тоді, коли користувач явно не змусив її з’являтися (утримуючи меню).

Примітка. Якщо ви хочете зробити це в Котліні, використовуйте: 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)
 }

14
Завдяки цьому, здається, це чудово працює, якщо використовувати 0 як другий параметр. Але якщо я використовую InputMethodManager.HIDE_IMPLICIT_ONLY, клавіатура ніколи не ховається (хоча я не затримую меню). Якісь підказки?
RoflcoptrException

27
Класно. Просто для уточнення, це відхиляє його лише у разі наявності, але не заважатиме йому вискочити, правда?
Чезмайстер

15
Можливо, буде корисно зателефонувати editText.clearFocus () перед тим, як приховати програмне забезпечення SoftInput
user2224350

111
editText.clearFocus()Тоді дзвінки InputMethodManager.HIDE_IMPLICIT_ONLYнавіть працюють на4.1
lanser12

11
Те, що працювало для мене на 4.4 / htc, було виконати, View focused = getCurrentFocus()щоб отримати те, що, безумовно, зосереджений на даний момент погляд, дзвінки focused.clearFocus(), а потім inputMethodManager.hideSoftInputFromWindow(focused.getWindowToken(), 0)(з чіткими прапорами).
Іонокласт Брігхем,

805

Також корисно для приховування програмної клавіатури:

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

Це можна використовувати для придушення програмної клавіатури, поки користувач фактично не торкнеться перегляду editText.


116
Ви можете домогтися того ж ефекту, додавши android: windowSoftInputMode = "stateHidden" на свою активність у маніфесті.
BoD

7
Спробував це у фрагменті (посилаючись на активність володіння) на рівні 9 API, і це, на жаль, не вийшло. Спробував викликати його в onResume і onActivityCreate - ніякого ефекту.
AgentKnopf

2
Я працюю в діалозі, і це спрацювало. Я використовую Android 3.2. Я помістив його в метод onCreateDialog (Bundle). У методі onCreate він не працював. Діалогове вікно діалогу = super.onCreateDialog (збереженийInstanceState); dialog.getWindow (). setSoftInputMode (WindowManager.LayoutParams. SOFT_INPUT_STATE_ALWAYS_HIDDEN); Як результат, мій погляд на EditTexts в ньому відображається без клавіатури. Коли користувач торкається редагування тексту, відображається клавіатура.
flobacca

4
Це не працює, якщо фокус все ще знаходиться в EditText (наприклад, після натискання кнопки). Використовуйте для цього рішення Reto.
Номенон

4
Чому важливі параметри маніфесту є поганою ідеєю? Я називаю це з фрагмента. Немає явного налаштування, яке стосується фрагмента ...
Грег Енніс

348

У мене є ще одне рішення для приховування клавіатури:

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

Тут проходять HIDE_IMPLICIT_ONLYна позиції showFlagі 0на позиції hiddenFlag. Це насильно закриє м'яку клавіатуру.


4
Ви використовуєте прапор приховування в параметрі showflags. Це працює лише тому, що константи використовують однакові цілі числа. Приклад з використанням правильних прапорів
Олексій

перевірено на Android 4.0, мені подобається це рішення, тому що у мене є кілька редагування текстів, кнопок цієї активності, на які можна зосередити увагу

32
@Mark: Оскільки метод називається "toggleSoftInput", а не "hidSoftInput" :)
Sver

19
Це рішення показує клавіатуру, якщо вона прихована. Це не правильно
Михайло Катков

1
@AkashAggarwal - "працює", якщо ви ігноруєте той факт, що він працював лише для вас, оскільки клавіатура показувала. (ВІДТВОРЮЄ видимість клавіатури: вона ховається, коли її показує, АЛЕ це показує, коли вона прихована !!) Чи можете ви гарантувати, що за будь-яких обставин, на всіх пристроях, для всіх майбутніх версій Android, що клавіатура НЕ буде показує, коли ви це називаєте? Якщо так, то продовжуйте і використовуйте його!
ToolmakerSteve

148

Рішення Мейєра працює і для мене. У моєму випадку найвищим рівнем мого додатка є tabHost, і я хочу приховати ключове слово при переключенні вкладок - я отримую маркер вікна з вкладкиHost View.

tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    public void onTabChanged(String tabId) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(tabHost.getApplicationWindowToken(), 0);
    }
}

У мене це працює і з SearchView. Дивіться нижче мою відповідь. Дякую mckoss!
Azurespot

138

Спробуйте цей код нижче onCreate()

EditText edtView=(EditText)findViewById(R.id.editTextConvertValue);
edtView.setInputType(0);

2
Цей метод працює як засіб усунення помилки "не можу приховати м'яку клавіатуру" в 2.0 та 2.1, як описано в code.google.com/p/android/isissue/detail?id=7115 ... перерахований вище не працював, коли я його спробував, але editView.setInputType (0) зробив.
Спайк Вільямс

18
Це законно на Javadoc (не на хак), хоча я б переписав метод якeditView.setInputType(InputType.TYPE_NULL);
Bostone

3
це працює, однак, він приховує android: hint. Я використовую Android 1.5
Тіртха

це чудово, коли вам потрібно закрити клавіатуру з діалогового вікна, не потрібно отримувати екземпляр чи інше, і ви можете призначити це всім текстам редагування, коли користувач натискає кнопку, яка закриває діалог
I_With_Stupid

Це працює, але також приховує курсор. Мені потрібен курсор, але немає системної клавіатури.
Стефан Брендле

128

Оновлення: я не знаю, чому це рішення вже не працює (я лише тестував на Android 23). Будь ласка, використовуйте замість цього рішення Саурабх Парік . Ось:

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 (), але клавіатура ніколи не приховується
користувач2236096

не працює, перевірено в radioGroup.setOnCheckedChangeListener, API 23
Christian Schäfer

Якщо придивитись ближче, InputMethodManager.HIDE_IMPLICIT_ONLY та InputMethodManager.SHOW_IMPLICIT мають однакове значення, яке є "1", тому різниці між цими викликами немає. => не працює
Palejandro

якщо виклику im.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 , все вдасться змінити, можливо, частково поганий дизайн ... Ми пишемо недбало, потім викреслюємо все і переписуємо все.
Король-король

88
protected void hideSoftKeyboard(EditText input) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}

5
Це працювало для мене! Але чому ви поставили input.setInputType (0) ? Я не міг взаємодіяти з EditTextView, коли у мене був цей рядок коду (Він працював, коли я його видалив).
ymerdrengene

Напевно input.getContext().getSystemService(Context.INPUT_METHOD_SERVICE).
CoolMind

Я видалив input.setInputType(0);цей код. Це змінило поведінку клавіатури і inputTypeдля EditText.
CoolMind

73

Якщо всі інші відповіді тут не працюють для вас так, як ви хотіли б їх, є ще один спосіб керування клавіатурою вручну.

Створіть функцію, яка буде керувати деякими EditTextвластивостями.

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

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

Потім переконайтесь, що onFocus 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);

+1 - Якщо ви хочете розпочати діяльність із закритою клавіатурою, використовуйте це рішення та додайте он-кліклістер, який встановлює setEditTextFocus (вірно). Працює як шарм!
шлінгел

У 7-му та 10-му рядках другого блоку коду я отримав "Неможливо вирішити контекст символу".
gimmegimme

Використовуйте замість 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();
Johan S

Це найбільш вичерпна відповідь, яка охоплює як шоу, так і приховування.
Андре Стальц

4
Ні. На моїй вкладці Samsung Android, 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);

Єдиний, хто працював для мене на 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. Просто подивіться, як поводиться EditTextз a android:imeOptions="actionDone", ви хочете досягти тієї ж поведінки тими самими засобами.


Перевірте цю відповідь


Це - відповідь. Єдиний метод, що працює в крос-версії. Я повернувся до цього питання, щоб опублікувати цю відповідь, тому що я не думав, що хтось ще знає
Ной Пассалакква

Це має бути правильна відповідь. Замість того, щоб обманювати Android, щоб приховати клавіатуру, коли вона дійсно повинна бути там, ми говоримо їй, що користувач робить це, що, в свою чергу, запускає те саме ім’я ImeAction [дурне ім'я, я визнаю], як ніби користувач натиснув "ЗРОБАНО" на клавіатурі . Таким чином, це не має значення, якщо користувач підтвердить введення даних на клавіатурі або натискає кнопку користувальницького інтерфейсу.
Олівер Хауслер

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 ()" повертає помилково!
xpto

Звичайно, так і потрібно. А може, я вас не розумію. У будь-якому випадку, ви можете доповнити клас hide()і show()методи, щоб мати більше контролю над тим, коли він повинен показувати, а коли ні. Для мене працює, я теж це зробив :) Я відредагую приклад
slinden77

@YoushaAleayoub так, так і буде. KeyBoard.toggle(fragment.getActivity())
slinden77

@ slinden77, lol, я кажу про вашу відповідь ... не цю, яку ви прокоментували. Тож ця відповідь все-таки НЕЧАСНА.
Yousha Aleayoub

@YoushaAleayoub uhm так, так і буде. Оригінальне запитання не згадує фрагменти, ви саме той, хто згадав фрагменти. Тож моя відповідь цілком справедлива. Щоб використовувати його з фрагментами, викличте метод інакше 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, доданий за допомогою 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) або в декларації XML TextView:

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

Оновлення: щойно знайшли діалоги, які ніколи не показують клавіатуру та працює у всіх версіях:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
        WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

Дякую. Два прапори FLAG_ALT_FOCUSABLE_IM та FLAG_ALT_FOCUSABLE_IM - це єдине, що допомогло в моєму випадку. Я не хотів, щоб клавіатура відображалася в моїй діяльності - навіть коли користувач натискав на текст редагування. (Я зробив власну «клавіатуру»).
Даніель Новак

Холодне рішення, однак, якщо ваша передня активність не є повноекранною, за нею видно клавіатуру. Також досі помітна допомога щодо переміщення курсора на клавіатурі. І це не шкірно.
халксінат

Я другий, що. З усіх можливих способів працює лише метод getWindow (). SetFlags (), принаймні на складі Android 5.1. Зауважте, що setSoftInputShownOnFocus () тепер встановленийShowSoftInputOnFocus () і більше не приховується, але не працює, принаймні не тоді, коли користувач торкається поля.
олефевр

Ваше "оновлення" було для мене єдиним робочим рішенням. Я шукаю рішення як мінімум дві години :)
Стефан Брендл

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

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

Це призводить до того, що поточна активність зберігає стан у пакеті, після чого активність починається, проходячи через булевий сигнал, який вказує, чи слід показувати або приховувати клавіатуру.

Усередині методу 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. Єдиним недоліком такого підходу є те, що потрібно бути обережними в роботі із кнопкою "назад". Оскільки в моєму додатку по суті є лише один екран (його калькулятор), я можу перекрити onBackPress () і повернутися на головний екран пристроїв.


1
детальне вирішення, але я думаю, що це занадто багато, щоб відтворити тисячі об'єктів, щоб приховати клавіатуру. Я не знаю, хто створив IMM для андроїда, але він пахне API для Windows. На мій погляд, хороший IME повинен мати два способи: сховати і показати :-)
rupps

Це все правда, але в моєму вирішенні є одна перевага - це завжди працює! Я не міг би знайти іншого рішення, яке завжди перемикало б клавіатуру, незалежно від того, які поля в інтерфейсі мають фокус, що користувач зробив для перемикання та клавіатури та яку версію андроїда вони виконують: - \
Лука Слєман

Людина, я абсолютно відчайдушно ховаю клавіатуру. Перепробував тисячі речей і нічого не працює. Але ваше вирішення для мене занадто багато, мені доведеться відтворити як 10 фрагментів, ініціалізувати служби, видалити багато слабких референцій .... ви знаєте? GC просто викине як 25mb: S ... Ще шукаю надійний спосіб це зробити :(
rupps

@Dmitry добре, це не привіт світ ... це складний додаток для планшетів. Я відмовляюся повністю вивантажувати його з пам'яті, щоб приховати нерозумну клавіатуру ... У будь-якому випадку я знайшов щось, що працює, поєднуючи тисячі запропонованих тут рішень :)
rupps

27

Як варіант цього рішення навколо , якщо ви хочете закрити м'яку клавіатуру з будь-якого місця, не маючи посилання на поле (EditText), яке використовувалося для відкриття клавіатури, але все-таки хотіли це зробити, якщо поле було зосереджене, ви можете використовувати це (від діяльності):

if (getCurrentFocus() != null) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

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

18

Якщо ви хочете закрити м'яку клавіатуру під час блоку або функціонального тестування, це можна зробити, натиснувши кнопку "назад" у вашому тесті:

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

Я ставлю "кнопку назад" у лапках, оскільки вищезазначене не викликає onBackPressed()активність для відповідної діяльності. Він просто закриває клавіатуру.

Не забудьте зробити деякий час призупинення, перш ніж продовжувати роботу, оскільки це займе трохи часу, щоб закрити кнопку назад, тому наступні клацання на Перегляд тощо не будуть зареєстровані лише після короткої паузи (одна секунда досить довга назва ).


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

1
Подумайте, я спробував 10 відповідей перед цим. Відмовився від надії. Спасибі людина.
Боллінг

Що таке mRootView?
justdan0227

14

Додайте свою активність android:windowSoftInputMode="stateHidden"у файлі Manifest. Приклад:

<activity
            android:name=".ui.activity.MainActivity"
            android:label="@string/mainactivity"
            android:windowSoftInputMode="stateHidden"/>

14

Простий і простий у використанні метод, просто зателефонуйте на skrKeyboardFrom (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);
}

Добре працює. Спасибі
Аліф

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)); im.hideSoftInputFromWindow (getWindow (). getCurrentFocus (). getWindowToken (), 0);
zmicer


12

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

Використання InputMethodManager не закривало клавіатуру. Мені довелося очистити фокус і встановити фокусируемость вигляду пошуку на помилкове:

mSearchView.clearFocus();
mSearchView.setFocusable(false);

1
Дуже розумний. Якщо користувач хоче іншого пошуку, просто натисніть пошук ще раз.
Алекс

SearchView не має на clearFocus()сторінках API Android, тому для мене це не спрацювало, але було інше рішення (див. Мою відповідь нижче).
Azurespot


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

1
Це рішення краще, тому що ви не маєте права контролювати, який EditText передавати як параметр методу hidSoftInputFromWindow () Це чудово працює !!
Billyjoker

12

Я майже спробував усі ці відповіді, у мене були деякі випадкові проблеми, особливо з галактикою Samsung Samsung 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);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.