Как скрыть мягкую клавиатуру на андроиде после нажатия на кнопку EditText?

Хорошо, все знают, что для скрытия клавиатуры вам нужно реализовать:

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); 

Но большое дело здесь в том, как скрыть клавиатуру, когда пользователь прикасается или выбирает любое другое место, которое не является EditText или softKeyboard?

Я попытался использовать onTouchEvent() в моей родительской Activity но это работает только в том случае, если пользователь касается вне любого другого вида, и нет прокрутки.

Я попытался реализовать прикосновение, щелчок, прослушиватель фокуса без каких-либо успехов.

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

Есть ли стандартный способ сделать это? В iPhone это было очень просто.

Solutions Collecting From Web of "Как скрыть мягкую клавиатуру на андроиде после нажатия на кнопку EditText?"

Следующий фрагмент просто скрывает клавиатуру:

 public static void hideSoftKeyboard(Activity activity) { InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService( Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow( activity.getCurrentFocus().getWindowToken(), 0); } 

Вы можете поместить это в класс утилиты, или если вы определяете его в рамках действия, избегаете параметра активности или вызываете hideSoftKeyboard(this) .

Самая сложная часть – когда звонить. Вы можете написать метод, который выполняет итерацию через каждый View в вашей активности и проверяет, является ли это instanceof EditText если он не регистрирует setOnTouchListener для этого компонента, и все будет падать на место. Если вам интересно, как это сделать, на самом деле это довольно просто. Вот что вы делаете, вы пишете рекурсивный метод вроде следующего, на самом деле вы можете использовать это, чтобы что-то сделать, например, настроить пользовательские шрифты и т. Д. Вот метод

 public void setupUI(View view) { // Set up touch listener for non-text box views to hide keyboard. if (!(view instanceof EditText)) { view.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { hideSoftKeyboard(MyActivity.this); return false; } }); } //If a layout container, iterate over children and seed recursion. if (view instanceof ViewGroup) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { View innerView = ((ViewGroup) view).getChildAt(i); setupUI(innerView); } } } 

Вот и все, просто вызовите этот метод после того, как вы setContentView в свою деятельность. В случае, если вам интересно, какой параметр вы передадите, это id родительского контейнера. Назначьте id родительскому контейнеру, например

<RelativeLayoutPanel android:id="@+id/parent"> ... </RelativeLayout>

И вызвать setupUI(findViewById(R.id.parent)) , то есть все.

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

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

Если вы используете более одного действия, определите общий идентификатор родительского макета, например <RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>

Затем setupUI(findViewById(R.id.main_parent)) класс из Activity и определите setupUI(findViewById(R.id.main_parent)) Внутри OnResume() и расширьте этот класс вместо “ Activity in your program

Вы можете добиться этого, выполнив следующие шаги:

  1. Сделайте родительский вид (просмотр содержимого вашей деятельности) интерактивным и настраиваемым, добавив следующие атрибуты

      android:clickable="true" android:focusableInTouchMode="true" 
  2. Внедрить метод hideKeyboard ()

      public void hideKeyboard(View view) { InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); } 
  3. Наконец, установите onFocusChangeListener вашего edittext.

      edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { hideKeyboard(v); } } }); 

Как указано в одном из приведенных ниже комментариев, это может не сработать, если родительское представление представляет собой ScrollView. В этом случае интерактивный и focusableInTouchMode может быть добавлен в представлении непосредственно под ScrollView.

Я считаю, что принятый ответ немного сложный.

Вот мое решение. Добавьте OnTouchListener в свой основной макет, например .:

 findViewById(R.id.mainLayout).setOnTouchListener(this) 

И поместите следующий код в метод onTouch.

 InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); 

Таким образом, вам не нужно перебирать все виды.

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

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

Здесь передайте HIDE_IMPLICIT_ONLY в позиции showFlag и 0 в позиции hiddenFlag . Он будет принудительно закрывать мягкую клавиатуру.

Ну, мне удалось несколько решить проблему, я переопределил dispatchTouchEvent в своей деятельности, там я использую следующее, чтобы скрыть клавиатуру.

  /** * Called to process touch screen events. */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: touchDownTime = SystemClock.elapsedRealtime(); break; case MotionEvent.ACTION_UP: //to avoid drag events if (SystemClock.elapsedRealtime() - touchDownTime <= 150){ EditText[] textFields = this.getFields(); if(textFields != null && textFields.length > 0){ boolean clickIsOutsideEditTexts = true; for(EditText field : textFields){ if(isPointInsideView(ev.getRawX(), ev.getRawY(), field)){ clickIsOutsideEditTexts = false; break; } } if(clickIsOutsideEditTexts){ this.hideSoftKeyboard(); } } else { this.hideSoftKeyboard(); } } break; } return super.dispatchTouchEvent(ev); } 

EDIT: метод getFields () – это просто метод, который возвращает массив с текстовыми полями в представлении. Чтобы избежать создания этого массива при каждом касании, я создал статический массив sFields, который возвращается в методе getFields (). Этот массив инициализируется в методах onStart (), таких как:

sFields = new EditText[] {mUserField, mPasswordField};


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

Тем не менее приветствуются более чистые и более короткие решения

Используйте OnFocusChangeListener .

Например:

 editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { hideKeyboard(); } } }); 

Обновление : вы также можете переопределить onTouchEvent() в своей деятельности и проверить координаты касания. Если координаты находятся за пределами EditText, тогда скройте клавиатуру.

Я применил dispatchTouchEvent в Activity для этого:

 private EditText mEditText; private Rect mRect = new Rect(); @Override public boolean dispatchTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); int[] location = new int[2]; mEditText.getLocationOnScreen(location); mRect.left = location[0]; mRect.top = location[1]; mRect.right = location[0] + mEditText.getWidth(); mRect.bottom = location[1] + mEditText.getHeight(); int x = (int) ev.getX(); int y = (int) ev.getY(); if (action == MotionEvent.ACTION_DOWN && !mRect.contains(x, y)) { InputMethodManager input = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); input.hideSoftInputFromWindow(mEditText.getWindowToken(), 0); } return super.dispatchTouchEvent(ev); } 

И я протестировал его, отлично работает!

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

Мне нужно это поведение для всех моих действий, поэтому я создал класс CustomActivity, наследующий от класса Activity, и «подключил» функцию dispatchTouchEvent . В основном есть два условия:

  1. Если фокус не изменился, и кто-то выстукивает за пределами текущего поля ввода, то отклоните IME
  2. Если фокус изменился, и следующий сфокусированный элемент не является экземпляром какого-либо поля ввода, то отклоните IME

Это мой результат:

 @Override public boolean dispatchTouchEvent(MotionEvent ev) { if(ev.getAction() == MotionEvent.ACTION_UP) { final View view = getCurrentFocus(); if(view != null) { final boolean consumed = super.dispatchTouchEvent(ev); final View viewTmp = getCurrentFocus(); final View viewNew = viewTmp != null ? viewTmp : view; if(viewNew.equals(view)) { final Rect rect = new Rect(); final int[] coordinates = new int[2]; view.getLocationOnScreen(coordinates); rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight()); final int x = (int) ev.getX(); final int y = (int) ev.getY(); if(rect.contains(x, y)) { return consumed; } } else if(viewNew instanceof EditText || viewNew instanceof CustomEditText) { return consumed; } final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0); viewNew.clearFocus(); return consumed; } } return super.dispatchTouchEvent(ev); } 

Сторона примечания: Кроме того, я назначаю эти атрибуты корневому представлению, позволяя очистить фокус на каждом поле ввода и не позволяя полям ввода получать фокус на запуске активности (делая просмотр содержимого «уловителем фокуса»):

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final View view = findViewById(R.id.content); view.setFocusable(true); view.setFocusableInTouchMode(true); } 

Я изменил решение Andre Luis IM, которого я достиг этого:

Я создал утилиту, чтобы скрыть мягкую клавиатуру так же, как и Andre Luiz IM:

 public static void hideSoftKeyboard(Activity activity) { InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0); } 

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

 findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Utils.hideSoftKeyboard(activity); return false; } }); 

Переопределить общедоступное логическое событие dispatchTouchEvent (событие MotionEvent) в любой активности (или расширить класс Activity)

 @Override public boolean dispatchTouchEvent(MotionEvent event) { View view = getCurrentFocus(); boolean ret = super.dispatchTouchEvent(event); if (view instanceof EditText) { View w = getCurrentFocus(); int scrcoords[] = new int[2]; w.getLocationOnScreen(scrcoords); float x = event.getRawX() + w.getLeft() - scrcoords[0]; float y = event.getRawY() + w.getTop() - scrcoords[1]; if (event.getAction() == MotionEvent.ACTION_UP && (x < w.getLeft() || x >= w.getRight() || y < w.getTop() || y > w.getBottom()) ) { InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0); } } return ret; } 

И это все, что вам нужно сделать

Мне понравился подход вызова dispatchTouchEvent сделанный htafoya, но:

  • Я не понял часть таймера (не знаю, зачем нужно измерять время простоя)?
  • Я не люблю регистрировать / отменять регистрацию всех EditTexts при каждом изменении вида (может быть довольно много изменений и редакторов в сложных иерархиях)

Итак, я сделал это несколько проще:

 @Override public boolean dispatchTouchEvent(final MotionEvent ev) { // all touch events close the keyboard before they are processed except EditText instances. // if focus is an EditText we need to check, if the touchevent was inside the focus editTexts final View currentFocus = getCurrentFocus(); if (!(currentFocus instanceof EditText) || !isTouchInsideView(ev, currentFocus)) { ((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE)) .hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } return super.dispatchTouchEvent(ev); } /** * determine if the given motionevent is inside the given view. * * @param ev * the given view * @param currentFocus * the motion event. * @return if the given motionevent is inside the given view */ private boolean isTouchInsideView(final MotionEvent ev, final View currentFocus) { final int[] loc = new int[2]; currentFocus.getLocationOnScreen(loc); return ev.getRawX() > loc[0] && ev.getRawY() > loc[1] && ev.getRawX() < (loc[0] + currentFocus.getWidth()) && ev.getRawY() < (loc[1] + currentFocus.getHeight()); } 

Существует один недостаток:

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

Способ отображения / скрытия мягкой клавиатуры

 InputMethodManager inputMethodManager = (InputMethodManager) currentActivity.getSystemService(Context.INPUT_METHOD_SERVICE); if (isShow) { if (currentActivity.getCurrentFocus() == null) { inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); } else { inputMethodManager.showSoftInput(currentActivity.getCurrentFocus(), InputMethodManager.SHOW_FORCED); } } else { if (currentActivity.getCurrentFocus() == null) { inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0); } else { inputMethodManager.hideSoftInputFromInputMethod(currentActivity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } } 

Надеюсь, они были полезны

Вот еще один вариант ответа fje, в котором рассматриваются вопросы, поднятые sosite.

Идея здесь состоит в том, чтобы обрабатывать как вниз, так и вверх действия в методе dispatchTouchEvent Activity. В действии «вниз» мы отмечаем сосредоточенное в данный момент представление (если оно есть) и находилось ли в нем касание, сохраняя оба этих фрагмента информации позже.

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

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

В противном случае мы его закрываем.

Итак, подведем итог: это работает следующим образом:

  • При касании внутри текущего сфокусированного EditText клавиатура остается открытой
  • При переходе от сфокусированного EditText к другому EditText клавиатура остается открытой (не закрывается / не открывается)
  • При касании где-либо вне текущего сфокусированного EditText который не является другим EditText , клавиатура закрывается
  • При длительном нажатии в EditText чтобы вызвать контекстную панель действий (с кнопками cut / copy / paste), клавиатура остается открытой, даже если действие UP произошло за пределами сфокусированного EditText (который перемещался вниз, чтобы освободить место для ТАКСИ). Обратите внимание, что при нажатии кнопки в CAB она закрывает клавиатуру. Это может быть нежелательным или нежелательным; Если вы хотите вырезать / скопировать из одного поля и вставить в другое, это будет так. Если вы хотите вставить обратно в тот же EditText , это не так.
  • Когда сфокусированный EditText находится в нижней части экрана, и вы долго нажимаете на какой-либо текст для его выбора, EditText сохраняет фокус, и поэтому клавиатура открывается так, как вы хотите, потому что мы делаем «касание в пределах границ обзора» на Вниз, а не вверх.

     private View focusedViewOnActionDown; private boolean touchWasInsideFocusedView; @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: focusedViewOnActionDown = getCurrentFocus(); if (focusedViewOnActionDown != null) { final Rect rect = new Rect(); final int[] coordinates = new int[2]; focusedViewOnActionDown.getLocationOnScreen(coordinates); rect.set(coordinates[0], coordinates[1], coordinates[0] + focusedViewOnActionDown.getWidth(), coordinates[1] + focusedViewOnActionDown.getHeight()); final int x = (int) ev.getX(); final int y = (int) ev.getY(); touchWasInsideFocusedView = rect.contains(x, y); } break; case MotionEvent.ACTION_UP: if (focusedViewOnActionDown != null) { // dispatch to allow new view to (potentially) take focus final boolean consumed = super.dispatchTouchEvent(ev); final View currentFocus = getCurrentFocus(); // if the focus is still on the original view and the touch was inside that view, // leave the keyboard open. Otherwise, if the focus is now on another view and that view // is an EditText, also leave the keyboard open. if (currentFocus.equals(focusedViewOnActionDown)) { if (touchWasInsideFocusedView) { return consumed; } } else if (currentFocus instanceof EditText) { return consumed; } // the touch was outside the originally focused view and not inside another EditText, // so close the keyboard InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow( focusedViewOnActionDown.getWindowToken(), 0); focusedViewOnActionDown.clearFocus(); return consumed; } break; } return super.dispatchTouchEvent(ev); } 

Прошу: Я признаю, что у меня нет влияния, но, пожалуйста, серьезно отнеситесь к моему ответу.

Проблема. Отключите мягкую клавиатуру при нажатии на клавиатуре или редактировании текста с минимальным кодом.

Решение: Внешняя библиотека известна как Butterknife.

Однолинейное решение:

 @OnClick(R.id.activity_signup_layout) public void closeKeyboard() { ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } 

Более читаемое решение:

 @OnClick(R.id.activity_signup_layout) public void closeKeyboard() { InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } 

Объяснение: Привяжите OnClick Listener к родительскому идентификатору XML макета активности, чтобы любой щелчок по макету (а не редактированию текста или клавиатуры) запустил этот фрагмент кода, который скроет клавиатуру.

Пример. Если ваш файл макета – R.layout.my_layout, а ваш идентификатор макета – R.id.my_layout_id, тогда ваш вызов привязки Butterknife должен выглядеть так:

 (@OnClick(R.id.my_layout_id) public void yourMethod { InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } 

Butterknife Documentation Ссылка: http://jakewharton.github.io/butterknife/

Plug: Butterknife произведет революцию в развитии Android. Подумайте.

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

Существует более простой подход, основанный на том же выпуске iPhone. Просто переопределите макет фона на сенсорном событии, где содержится текст редактирования. Просто используйте этот код в OnCreate (login_fondo – корневой макет):

  final LinearLayout llLogin = (LinearLayout)findViewById(R.id.login_fondo); llLogin.setOnTouchListener( new OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent ev) { InputMethodManager imm = (InputMethodManager) mActivity.getSystemService( android.content.Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mActivity.getCurrentFocus().getWindowToken(), 0); return false; } }); 

Попробуйте включить stateHidden в качестве значения вашей активности. ЗначениеSoftInputMode

http://developer.android.com/reference/android/R.attr.html#windowSoftInputMode

Например, для вашей деятельности:

 this.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); 

Его слишком просто, просто сделайте свой недавний макет кликабельным, настраиваемым с помощью этого кода:

 android:id="@+id/loginParentLayout" android:clickable="true" android:focusableInTouchMode="true" 

А затем написать метод и OnClickListner для этого макета, так что когда самый верхний макет коснется любого, где он вызовет метод, в котором вы будете писать код, чтобы убрать клавиатуру. Ниже приведен код для обоих; // вы должны написать это в OnCreate ()

  yourLayout.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view) { hideKeyboard(view); } }); 

Метод, вызванный из списка: –

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

Это немного измененная версия ответа fje, которая в основном работала отлично.

Эта версия использует ACTION_DOWN, поэтому выполнение действия прокрутки также закрывает клавиатуру. Он также не распространяется на событие, если вы не нажмете на другой EditText. Это означает, что щелчок в любом месте вне вашего EditText, даже на другом кликабе, просто закрывает клавиатуру.

 @Override public boolean dispatchTouchEvent(MotionEvent ev) { if(ev.getAction() == MotionEvent.ACTION_DOWN) { final View view = getCurrentFocus(); if(view != null) { final View viewTmp = getCurrentFocus(); final View viewNew = viewTmp != null ? viewTmp : view; if(viewNew.equals(view)) { final Rect rect = new Rect(); final int[] coordinates = new int[2]; view.getLocationOnScreen(coordinates); rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight()); final int x = (int) ev.getX(); final int y = (int) ev.getY(); if(rect.contains(x, y)) { super.dispatchTouchEvent(ev); return true; } } else if(viewNew instanceof EditText || viewNew instanceof CustomEditText) { super.dispatchTouchEvent(ev); return true; } final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0); viewNew.clearFocus(); return true; } } return super.dispatchTouchEvent(ev); } 

Другая идея – переопределить метод onInterceptTouchEvent в корневом представлении для вашей активности.

Событие касания идет от фронтального вида на экране (где произошло событие касания) вниз по onTouch представлений, вызывающего метод onTouch пока какое-либо из представлений не вернется, что указывает на то, что событие касания было уничтожено. Поскольку многие из просмотров потребляют событие касания по умолчанию (например, в случае с EditText или TextView ), это событие не попадает в метод корневого представления onTouch .

Но, прежде чем совершить этот обход, событие касания перемещается по другому пути, переходя от корневого представления вниз до дерева представлений, пока он не достигнет фронтального вида. Этот обход выполняется путем вызова onInterceptTouchEvent . Если метод возвращает true, он перехватывает событие … nahhh, но это немного трюк, я не думаю, что вы хотите это сделать и не знать деталей. Что вам нужно знать, так это то, что вы можете переопределить этот метод в корневом представлении для своей деятельности и поместить там код, чтобы скрыть клавиатуру, когда это необходимо.

Я получил эту работу с небольшим вариантом решения Fernando Camarago. В моем методе onCreate я присоединяю один onTouchListener к корневому представлению, но отправляю в качестве аргумента представление, а не активность.

  findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { Utils.hideSoftKeyboard(v); return false; } }); 

В отдельном классе Utils есть …

  public static void hideSoftKeyboard(View v) { InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } 

Вы можете легко переопределить событие onKey () в активности и фрагментах, чтобы скрыть клавиатуру.

 @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (keyCode == event.KEYCODE_ENTER) { intiateLoginProcess(); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getWindow().getCurrentFocus() .getWindowToken(), 0); return true; } } return false; } 

Эй, ребята, у меня есть простое решение этой проблемы, и это решение можно использовать для простой регистрации или формы входа. Мое решение аналогично тому, как я реализовал в ios setontouch listener в Main view

Activity_main.xml добавить идентификатор к вашему основному относительному расположению android:id="@+id/mainlayout"

И добавьте этот код в свою деятельность

  RelativeLayout mainLayout = (RelativeLayout)findViewById(R.id.mainlayout); mainLayout.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub Log.d("Json Response", "Touch outside"); InputMethodManager inputMethodManager = (InputMethodManager) MainActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), 0); return false; } }); 

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

 public class DismissKeyboardListener implements OnClickListener { Activity mAct; public DismissKeyboardListener(Activity act) { this.mAct = act; } @Override public void onClick(View v) { if ( v instanceof ViewGroup ) { hideSoftKeyboard( this.mAct ); } } } public void hideSoftKeyboard(Activity activity) { InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); } 

the best practice here is to create a Helper class and every container Relative / Linear Layouts should implement this.

**** Take note only the main Container should implement this class (For optimization) ****

and implement it like this :

 Parent.setOnClickListener( new DismissKeyboardListener(this) ); 

the keyword this is for Activity. so if you are on fragment you use like getActivity();

—thumbs up if it help you… — cheers Ralph —

I thought this problem. first, I think that setOnTouchListener is not simple solution. so I believe dispatchTouchEvent is best simple solution.

 public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP) { View v = getCurrentFocus(); if (v instanceof EditText) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } } return super.dispatchKeyEvent(event); } 

in here, a important is ACTION_UP.

I assumed EditText only show soft keyboard otherwise not show the keyboard. I have tested on Android5.0.1 (G3.cat6 of LG).

if you need drag checking, long click, …, show comments above.

My solution hides keyboard on outside click in any activity, with of all edit texts. Without specifying them one by one.

First add to root view of layout xml: android:clickable="true" android:focusableInTouchMode="true"

Next, create one parent Acitvity of all activities you want to hide keyboard, and specify onResume() method:

  @Override protected void onResume() { super.onResume(); //getting Root View that gets focus View rootView =((ViewGroup)findViewById(android.R.id.content)). getChildAt(0); rootView.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { hideKeyboard(AbstractActivity.this); } } }); } 

Extend your activity with this General activity (Inheritance power !) and that's all, every time any EditText (on any extended Activity) will lose focus, keyboard will be hidden.

PS hideKeyboard method :

 public static void hideKeyboard(Activity context) { InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow( context.getCurrentFocus().getWindowToken(), 0); } 

context.getCurrentFocus() doesn't need specifying specific EditText view..

Я сделал так:

 @Override public boolean dispatchTouchEvent(MotionEvent ev) { View view = getCurrentFocus(); if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("android.webkit.")) { int scrcoords[] = new int[2]; view.getLocationOnScreen(scrcoords); float x = ev.getRawX() + view.getLeft() - scrcoords[0]; float y = ev.getRawY() + view.getTop() - scrcoords[1]; if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom()) hideKeyboard(this); } return super.dispatchTouchEvent(ev); } 

Hide keyboard code :

 public static void hideKeyboard(Activity act) { if(act!=null) ((InputMethodManager)act.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((act.getWindow().getDecorView().getApplicationWindowToken()), 0); } 

Готово

To solve this problem what you have to do is first use setOnFocusChangeListener of that Edittext

 edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { Log.d("focus", "focus loosed"); // Do whatever you want here } else { Log.d("focus", "focused"); } } }); 

and then what you need to do is override dispatchTouchEvent in the activity which contains that Edittext see below code

 @Override public boolean dispatchTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { View v = getCurrentFocus(); if ( v instanceof EditText) { Rect outRect = new Rect(); v.getGlobalVisibleRect(outRect); if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) { Log.d("focus", "touchevent"); v.clearFocus(); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } } } return super.dispatchTouchEvent(event); } 

Now what will happen is when a user click outside then firstly this dispatchTouchEvent will get called which then will clear focus from the editext now your OnFocusChangeListener will get called that focus has been changed now here you can do anything which you wanted to do hope it works

You can try the way below, it works great for me 🙂

This way can be applied for Activity or Fragment and it's also compatible with ScrollView.

We put ScrollView as a top-level layout, declare id parentView for the LinearLayout inside and add two attributes like below:

 android:id="@+id/parentView" android:clickable="true" android:focusableInTouchMode="true" 

In code, write a function like below:

 public static void hideSoftKeyboard (Activity activity) { InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0); } 

Then register an OnFocusChangeListener for the root view (write in onCreate method) to make all EditText in Activity affected:

 parentLayout.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { hideSoftKeyboard(your_activity_name.this); } } }); 

I have refined the method, put the following code in some UI utility class(preferably, not necessarily) so that it can be accessed from all your Activity or Fragment classes to serve its purpose.

 public static void serachAndHideSoftKeybordFromView(View view, final Activity act) { if(!(view instanceof EditText)) { view.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { hideSoftKeyboard(act); return false; } }); } if (view instanceof ViewGroup) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { View nextViewInHierarchy = ((ViewGroup) view).getChildAt(i); serachAndHideSoftKeybordFromView(nextViewInHierarchy, act); } } } public static void hideSoftKeyboard (Activity activity) { InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0); } 

Then say for example you need to call it from activity, call it as follows;

 UIutils.serachAndHideSoftKeybordFromView(findViewById(android.R.id.content), YourActivityName.this); 

уведомление

findViewById(android.R.id.content)

This gives us the root view of the current group(you mustn't have set the id on root view).

Приветствия 🙂

 @Override public boolean onTouchEvent(MotionEvent event) { InputMethodManager imm = (InputMethodManager)getSystemService(Context. INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); return true; }