Cerrar / ocultar el teclado virtual de Android

3820

Tengo una EditTexty una Buttonen mi diseño.

Después de escribir en el campo de edición y hacer clic en Button, quiero ocultar el teclado virtual. Supongo que este es un código simple, pero ¿dónde puedo encontrar un ejemplo?

Al tocar fuera del teclado.

Ak23
fuente
13
¿Qué sucede si solo tiene un EditText y varios botones, como casillas de verificación y radios? El único lugar donde necesita el teclado es en el único EditText. ¿Cómo se registra para saber que se eligió / hizo clic en otra cosa para ocultar el teclado?
AlikElzin-kilaka 01 de
14
me siento estupido. No puedo ocultar el teclado en ICS. Intenté todos los métodos aquí y combinaciones de ellos. De ninguna manera. El método para mostrarlo funciona, pero no puedo ocultarlo sin importar qué ficha de viento, ocultar banderas, configuraciones de manifiesto o velas para ningún santo. En el teclado siempre veo esto: I / LatinIME (396): InputType.TYPE_NULL se especifica W / LatinIME (396): Clase de entrada inesperada: inputType = 0x00000000 imeOptions = 0x00000000
rompe
44
/ ** * Este método se usa para ocultar el teclado virtual. * @param activity * / public void hideSoftKeyboard (Actividad de actividad) {InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService (Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow (activity.getCurrentFocus (). getWindowToken (), 0); }
Harshal Benake
esto funcionó para mí
nmxprime
Con los dispositivos que aumentan el tamaño y la resolución de la pantalla, la ocultación del teclado virtual se vuelve menos importante.
Al-Kathiri Khalid el

Respuestas:

2038

Para ayudar a aclarar esta locura, me gustaría comenzar disculpándome en nombre de todos los usuarios de Android por el tratamiento absolutamente ridículo del teclado suave de Google. La razón por la que hay tantas respuestas, cada una diferente, para la misma pregunta simple es porque esta API, como muchas otras en Android, está terriblemente diseñada. No se me ocurre ninguna forma cortés de decirlo.

Quiero esconder el teclado Espero para proporcionar Android con la siguiente afirmación: Keyboard.hide(). El fin. Muchas gracias. Pero Android tiene un problema. Debe usar el InputMethodManagerpara ocultar el teclado. OK, bien, esta es la API de Android para el teclado. ¡PERO! Debes tener un Contextpara poder acceder al IMM. Ahora tenemos un problema. Es posible que desee ocultar el teclado de una clase estática o de utilidad que no tiene uso o necesidad de ninguna Context. o Y MUCHO peor, el IMM requiere que especifique de qué View(o peor aún, de qué Window) quiere ocultar el teclado.

Esto es lo que hace que ocultar el teclado sea tan desafiante. Estimado Google: ¡Cuando busco la receta de un pastel, no hay nadie RecipeProvideren la Tierra que se niegue a proporcionarme la receta a menos que responda primero a QUIÉN se comerá el pastel Y dónde se comerá!

Esta triste historia termina con la fea verdad: para ocultar el teclado de Android, deberá proporcionar 2 formas de identificación: a Contexty a Viewo a Window.

He creado un método de utilidad estática que puede hacer el trabajo MUY sólidamente, siempre que lo llame desde un 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);
}

Tenga en cuenta que este método de utilidad SOLO funciona cuando se llama desde un Activity! El método anterior llama getCurrentFocusal objetivo Activitypara obtener el token de ventana adecuado.

Pero supongamos que desea ocultar el teclado de un EditTexthost en un DialogFragment? No puede usar el método anterior para eso:

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

¡Esto no funcionará porque pasará una referencia al Fragmenthost del sistema Activity, que no tendrá control enfocado mientras Fragmentse muestra! ¡Guauu! Entonces, para ocultar el teclado de los fragmentos, recurro al nivel inferior, más común y más feo:

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

A continuación hay información adicional obtenida de más tiempo perdido persiguiendo esta solución:

Acerca de windowSoftInputMode

Hay otro punto de contención a tener en cuenta. Por defecto, Android asignará automáticamente el foco inicial al primer EditTextcontrol enfocable en su Activity. Naturalmente, se deduce que InputMethod (generalmente el teclado virtual) responderá al evento de enfoque mostrándose. El windowSoftInputModeatributo en AndroidManifest.xml, cuando se establece en stateAlwaysHidden, indica al teclado que ignore este foco inicial asignado automáticamente.

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

Casi increíblemente, parece no hacer nada para evitar que el teclado se abra cuando se toca el control (a menos que focusable="false"y / o focusableInTouchMode="false"están asignados al control). Aparentemente, la configuración windowSoftInputMode se aplica solo a eventos de enfoque automático, no a eventos de enfoque activados por eventos táctiles.

Por lo tanto, stateAlwaysHiddenes MUY mal nombrado. Quizás debería llamarse en su ignoreInitialFocuslugar.

Espero que esto ayude.


ACTUALIZACIÓN: más formas de obtener un token de ventana

Si no hay una vista enfocada (por ejemplo, puede suceder si acaba de cambiar fragmentos), hay otras vistas que proporcionarán un token de ventana útil.

Estas son alternativas para el código anterior. if (view == null) view = new View(activity); No se refieren explícitamente a su actividad.

Dentro de una clase de fragmento:

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

Dado un fragmento fragmentcomo parámetro:

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

A partir de su cuerpo de contenido:

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

ACTUALIZACIÓN 2: enfoque claro para evitar mostrar el teclado nuevamente si abre la aplicación desde el fondo

Agregue esta línea al final del método:

view.clearFocus();

rmirabelle
fuente
2
Muy buen artículo. Sin embargo, una cosa es que si inicia otra actividad que activa el teclado, este seguirá estando presente cuando regrese. Se solucionó eso quitando el teclado usando su método al salir de la actividad principal.
Oyvind
3
@rmirabelle FragmentParece que puedes usarlogetActivity().getWindow().getDecorView()
McX
1
Esta publicación es genial, pero te faltan dos partes muy importantes. Los sutiles cambios realizados por versión y por fabricación. Por ejemplo, en un Samsung galaxy s6 necesitamos usar .clearFocus () antes de ocultar el teclado ... si no, el teclado todavía aparecerá en el segundo clic del texto de edición: S
Warpzit
17
Google realmente debería proporcionar esa Keyboard.hide();utilidad
HendraWD
1
[someView] .getContext () << Puede ser el caso de la actividad. Es el mismo objeto siempre. (Excepto servicios internos ...)
Oliver Dixon
4419

Puede forzar a Android a ocultar el teclado virtual usando InputMethodManager , llamando hideSoftInputFromWindowy pasando el token de la ventana que contiene su vista enfocada.

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

Esto obligará al teclado a ocultarse en todas las situaciones. En algunos casos, querrá pasar InputMethodManager.HIDE_IMPLICIT_ONLYcomo el segundo parámetro para asegurarse de que solo oculta el teclado cuando el usuario no lo forzó explícitamente a aparecer (manteniendo presionado el menú).

Nota: Si quieres hacer esto en Kotlin, usa: context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

Sintaxis de Kotlin

// 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
fuente
14
Gracias, esto parece funcionar muy bien si se usa 0 como segundo parámetro. Pero si uso InputMethodManager.HIDE_IMPLICIT_ONLY el teclado nunca está oculto (aunque no estoy presionando el menú). ¿Alguna pista?
RoflcoptrException
27
Frio. Solo para aclarar, esto solo lo descarta si está presente, pero no evitará que aparezca, ¿verdad?
Cheezmeister
15
Puede ser útil llamar a editText.clearFocus () antes de ocultar el softInput
user2224350
111
Llamando editText.clearFocus()a continuación, InputMethodManager.HIDE_IMPLICIT_ONLYfunciona incluso en4.1
sprocket12
11
Lo que funcionó para mí en 4.4 / htc se ejecutó View focused = getCurrentFocus()para obtener lo que definitivamente es la vista actualmente enfocada, la llamada focused.clearFocus()y luego inputMethodManager.hideSoftInputFromWindow(focused.getWindowToken(), 0)(con marcas claras).
Ionoclast Brigham
806

También es útil para ocultar el teclado virtual:

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

Esto se puede usar para suprimir el teclado virtual hasta que el usuario realmente toque la Vista editText.

Garnet Ulrich
fuente
116
También puede lograr el mismo efecto agregando android: windowSoftInputMode = "stateHidden" en su actividad en el manifiesto.
BoD
77
Intenté esto en un Fragmento (haciendo referencia a la actividad propietaria) en API Nivel 9 y desafortunadamente no funcionó. Intenté llamarlo en onResume y onActivityCreated - sin efecto.
AgentKnopf
2
Estoy trabajando en un diálogo y esto funcionó. Estoy usando Android 3.2. Lo puse en el método onCreateDialog (Bundle). No funcionó en el método onCreate. Diálogo de diálogo = super.onCreateDialog (savedInstanceState); dialog.getWindow (). setSoftInputMode (WindowManager.LayoutParams. SOFT_INPUT_STATE_ALWAYS_HIDDEN); El resultado es que mi vista con EditTexts aparece sin el teclado. Cuando el usuario toca un texto de edición, aparece el teclado.
flobacca
44
Esto no funciona cuando el foco todavía está en EditText (como, después de tocar un botón). Use la solución de Reto para eso.
Noumenon
44
¿Por qué anular la configuración del manifiesto es una mala idea? Estoy llamando a esto desde un fragmento. No hay una configuración de manifiesto que se aplique a un fragmento ...
Greg Ennis
349

Tengo una solución más para ocultar el teclado:

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

Aquí pasa HIDE_IMPLICIT_ONLYen la posición de showFlagy 0en la posición de hiddenFlag. Se cerrará con fuerza el teclado suave.

Saurabh Pareek
fuente
44
Estás utilizando una bandera de ocultar en el parámetro showflags. Esto solo funciona porque las constantes usan los mismos enteros. Ejemplo usando las banderas correctas
Alex
probado en Android 4.0, me gusta esta solución, porque tengo múltiples textos de edición, botones en esa actividad, que pueden tener foco
32
@ Mark: Debido a que el método se llama "toggleSoftInput", no "hideSoftInput" :)
Sver
19
Esta solución muestra el teclado si está oculto. No es correcto
Michael Katkov
1
@AkashAggarwal: "funciona" si ignoras el hecho de que solo funcionó para ti porque se estaba mostrando el teclado. (CAMBIA la visibilidad del teclado: se oculta cuando se muestra, ¡PERO lo muestra cuando está oculto!) ¿Puede GARANTIZAR que, en todas las circunstancias, en todos los dispositivos, para todas las versiones futuras de Android, el teclado NO será mostrando en el momento que llamas esto? Si es así, ¡adelante y úsalo!
ToolmakerSteve
149

La solución de Meier también funciona para mí. En mi caso, el nivel superior de mi aplicación es un tabHost y quiero ocultar la palabra clave cuando cambio de pestañas: obtengo el token de la ventana de la vista tabHost.

tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    public void onTabChanged(String tabId) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(tabHost.getApplicationWindowToken(), 0);
    }
}
mckoss
fuente
Tengo esto para trabajar con SearchView también. Vea a continuación mi respuesta. Gracias mckoss!
Azurespot
139

Por favor intente esto debajo del código en onCreate()

EditText edtView=(EditText)findViewById(R.id.editTextConvertValue);
edtView.setInputType(0);
Jeyavel
fuente
2
Este método funciona como una forma de evitar el error "no se puede ocultar el teclado virtual " en 2.0 y 2.1 como se describe en code.google.com/p/android/issues/detail?id=7115 ... el método hideSoftInputFromWindow enumerado anteriormente no funcionó cuando lo probé, pero editView.setInputType (0) sí.
Spike Williams el
18
Esto es legítimo por Javadoc (no es un truco), aunque reescribiría el método comoeditView.setInputType(InputType.TYPE_NULL);
Bostone
3
esto funciona, sin embargo, oculta el androide: pista. Estoy usando Android 1.5
Tirtha
Esto es ideal para cuando necesita cerrar el teclado desde un cuadro de diálogo, no necesita obtener una instancia ni nada y puede asignar esto a todos los textos de edición cuando el usuario presiona un botón que cierra el cuadro de diálogo
I'm_With_Stupid
Funciona, pero también está ocultando el cursor. Necesito el cursor, pero no el teclado del sistema.
Stefan Brendle
129

Actualización: no sé por qué esta solución ya no funciona (acabo de probar en Android 23). Utiliza la solución de Saurabh Pareek en su lugar. Aquí está:

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

Vieja respuesta:

//Show soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//hide keyboard :
 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Nguyen Minh Binh
fuente
8
¿Dónde debo colocar este código? He intentado pegar getWindow (). SetSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); en onCreate () pero el teclado no está oculto
user2236096
no funciona, probado en radioGroup.setOnCheckedChangeListener, API 23
Christian Schäfer
Si mira más de cerca, InputMethodManager.HIDE_IMPLICIT_ONLY y InputMethodManager.SHOW_IMPLICIT tienen el mismo valor, que es "1", por lo que no hay diferencia entre estas llamadas. => no funciona
Palejandro
si llama a imm.toggleSoftInput (InputMethodManager.HIDE_IMPLICIT_ONLY, 0); entonces el teclado se mostrará en la pantalla :) La mejor implementación es: github.com/ravindu1024/android-keyboardlistener Shame en Android SDK
Duna
I don't know why this solution is not work any more- porque es Android , todo podrá cambiar, tal vez en parte debido a un mal diseño ... Escribimos descuidadamente, luego tachamos todo y reescribimos todo.
Rey Rey
89
protected void hideSoftKeyboard(EditText input) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}
Sreedev R
fuente
55
¡Esto funcionó para mí! Pero, ¿por qué pusiste input.setInputType (0) ? No podía interactuar con EditTextView cuando tenía esa línea de código (funcionó cuando la eliminé ).
ymerdrengene
Probablemente input.getContext().getSystemService(Context.INPUT_METHOD_SERVICE).
CoolMind
Lo eliminé input.setInputType(0);de este código. Cambió el comportamiento del teclado y inputTypepara el EditText.
CoolMind
74

Si todas las otras respuestas aquí no funcionan para usted como le gustaría, hay otra forma de controlar manualmente el teclado.

Cree una función con la que administrará algunas de las EditTextpropiedades de:

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

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

Luego, asegúrese de que al enfocar EditTextcuando abra / cierre el teclado:

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

Ahora, cada vez que desee abrir el teclado, llame manualmente:

setEditTextFocus(true);

Y para cerrar la llamada:

setEditTextFocus(false);
Rotemmiz
fuente
+1: si desea comenzar una actividad con el teclado cerrado, use esta solución y agregue un onclicklistener que establezca setEditTextFocus (verdadero). Funciona como el encanto!
schlingel
Obtuve 'No se puede resolver el contexto del símbolo', en la séptima y décima línea del segundo bloque de código.
gimmegimme
Utilice getContext () en su lugar
Rotemmiz
61

Saurabh Pareek tiene la mejor respuesta hasta ahora.

Sin embargo, también podría usar las banderas correctas.

/* 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);

Ejemplo de uso real

/* 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 ... */
}
Alex
fuente
1
Este es el más eficiente para la última versión. Siempre será necesario ajustarlo para versiones anteriores. Especialmente antes de v3.
Alex
2
@Mazen: usofragment.getActivity().getSystemService();
Johan S
Esta es la respuesta más completa, que abarca tanto mostrar como ocultar.
André Staltz el
44
No. En mi Samsung Tab, Android 5.0, el llamado código de "ocultar teclado" de arriba CAMBIARÁ el teclado virtual; si ya está oculto, lo mostrará. Hay una razón por la que esta función tiene TOGGLE en el nombre.
ToolmakerSteve
57

de esa búsqueda, aquí encontré una respuesta que me funciona

// 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
fuente
El único que funcionó para mí para un Motorola con Android 5.1
GMX
55

La respuesta corta

En su OnClickoyente llame al onEditorActionde la EditTextconIME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

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

El desglose

Siento que este método es mejor, más simple y más alineado con el patrón de diseño de Android. En el ejemplo simple anterior (y generalmente en la mayoría de los casos comunes) tendrá un EditTextfoco que tiene / tuvo y también fue el que invocó el teclado en primer lugar (definitivamente es capaz de invocarlo en muchos escenarios comunes). De la misma manera, que debe ser el que para liberar el teclado, por lo general lo que puede hacerse por una ImeAction. Solo vea cómo se comporta un EditTextcon android:imeOptions="actionDone", desea lograr el mismo comportamiento por los mismos medios.


Comprueba esta respuesta relacionada

Alex.F
fuente
Esta es la respuesta. Único método que funciona en versión cruzada. Volví a esta pregunta para publicar esta respuesta porque no creía que nadie más lo supiera
Noah Passalacqua
Esta debería ser la respuesta correcta. En lugar de engañar a Android para que oculte el teclado cuando realmente debería estar allí, le decimos que el usuario ha terminado, lo que a su vez activa la misma ImeAction [nombre estúpido, lo admito] como si el usuario hubiera hecho clic en "HECHO" en el teclado . De esta manera, no hay diferencia si el usuario confirma la entrada en el teclado o toca el botón UI.
Oliver Hausler
46

Esto debería funcionar:

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);
revs slinden77
fuente
Funcionó en parte, incluso si se ocultó el teclado "isActive ()" devuelve falso!
xpto
Por supuesto que sí, se supone que debe hacerlo. O tal vez no te entiendo. De todos modos, se puede complementar con la clase hide()y show()métodos para tener más control sobre cuando debe mostrar y cuándo no. Funciona para mí, yo también lo hice :)
Editaré el
@YoushaAleayoub sí, lo hará. KeyBoard.toggle(fragment.getActivity())
slinden77
@ slinden77, lol, estoy hablando de tu respuesta ... no esta que has comentado. Entonces esa respuesta todavía NO funcionará.
Yousha Aleayoub
@YoushaAleayoub uhm sí, lo hará. La pregunta original no menciona fragmentos, usted es quien mencionó los fragmentos. Entonces mi respuesta es perfectamente válida. Para usarlo con fragmentos, llame al método de manera diferente a a Fragment, como un comentario. Aprenda a usar métodos, por favor, y luego regrese. Estás confundiendo a la gente con tus respuestas tontas
slinden77
43

Estoy usando un teclado personalizado para ingresar un número hexadecimal, así que no puedo mostrar el teclado IMM ...

En v3.2.4_r1 setSoftInputShownOnFocus(boolean show)se agregó para controlar el clima o no para mostrar el teclado cuando TextView obtiene el foco, pero todavía está oculto, por lo que se debe usar la reflexión:

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

Para versiones anteriores, obtuve muy buenos resultados (pero lejos de ser perfectos) con un OnGlobalLayoutListener, agregado con la ayuda de a ViewTreeObserverdesde mi vista raíz y luego comprobando si el teclado se muestra así:

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

Esta última solución puede mostrar el teclado por una fracción de segundo y se mete con los controladores de selección.

Cuando en el teclado ingresa a pantalla completa, onGlobalLayout no se llama. Para evitar eso, use TextView # setImeOptions (int) o en la declaración XML de TextView:

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

Actualización: Acabo de encontrar qué diálogos usan para nunca mostrar el teclado y funciona en todas las versiones:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
        WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
sergio91pt
fuente
Gracias. Las dos banderas FLAG_ALT_FOCUSABLE_IM y FLAG_ALT_FOCUSABLE_IM son realmente lo único que ayudó en mi caso. No quería que se mostrara un teclado en mi actividad, ni siquiera cuando el usuario hizo clic en editar texto. (Hice mi propio "teclado").
Daniel Novak
Solución genial, sin embargo, si su actividad frontal no es a pantalla completa, el teclado es visible detrás de él. También la ayuda para el movimiento del cursor del teclado también es visible. Y no es skinnable.
Halxinate el
Secundo que. De todas las formas posibles, solo funciona el método getWindow (). SetFlags (), al menos en Android 5.1. Tenga en cuenta que setSoftInputShownOnFocus () ahora está configurado como ShowSoftInputOnFocus () y ya no está oculto, pero no funciona, al menos no cuando el usuario toca el campo.
olefevre
Su "actualización" fue la única solución de trabajo para mí. Estoy buscando una solución al menos dos horas :)
Stefan Brendle
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
fuente
30

He pasado más de dos días trabajando en todas las soluciones publicadas en el hilo y he encontrado que carecen de una forma u otra. Mi requisito exacto es tener un botón que muestre u oculte con un 100% de confiabilidad el teclado en pantalla. Cuando el teclado está oculto, no debería volver a aparecer, sin importar en qué campos de entrada haga clic el usuario. Cuando está en su estado visible, el teclado no debe desaparecer sin importar en qué botones haga clic el usuario. Esto debe funcionar en Android 2.2+ hasta los últimos dispositivos.

Puede ver una implementación funcional de esto en mi aplicación RPN limpia .

Después de probar muchas de las respuestas sugeridas en varios teléfonos diferentes (incluidos los dispositivos froyo y gingerbread), se hizo evidente que las aplicaciones de Android pueden:

  1. Oculta temporalmente el teclado. Volverá a aparecer de nuevo cuando un usuario enfoque un nuevo campo de texto.
  2. Muestre el teclado cuando comience una actividad y establezca una bandera en la actividad que indique que su teclado siempre debe estar visible. Este indicador solo se puede establecer cuando se inicia una actividad.
  3. Marque una actividad para nunca mostrar o permitir el uso del teclado. Este indicador solo se puede establecer cuando se inicia una actividad.

Para mí, ocultar temporalmente el teclado no es suficiente. En algunos dispositivos, volverá a aparecer tan pronto como se enfoque un nuevo campo de texto. Como mi aplicación usa múltiples campos de texto en una página, enfocar un nuevo campo de texto hará que el teclado oculto vuelva a aparecer.

Lamentablemente, los elementos 2 y 3 de la lista solo funcionan con fiabilidad cuando se inicia una actividad. Una vez que la actividad se ha hecho visible, no puede ocultar o mostrar permanentemente el teclado. El truco consiste en reiniciar su actividad cuando el usuario presiona el botón de alternancia del teclado. En mi aplicación cuando el usuario presiona el botón de alternar teclado, se ejecuta el siguiente código:

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

Esto hace que la actividad actual tenga su estado guardado en un paquete, y luego se inicia la actividad, pasando por un valor booleano que indica si el teclado debe mostrarse u ocultarse.

Dentro del método onCreate se ejecuta el siguiente código:

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

Si se debe mostrar el teclado virtual, se le indica al InputMethodManager que muestre el teclado y se le indica a la ventana que haga siempre visible la entrada virtual. Si el teclado virtual debe estar oculto, se configura WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM.

Este enfoque funciona de manera confiable en todos los dispositivos que he probado, desde un teléfono HTC de 4 años con Android 2.2 hasta un nexus 7 con 4.2.2. La única desventaja con este enfoque es que debe tener cuidado al manejar el botón Atrás. Como mi aplicación esencialmente solo tiene una pantalla (es una calculadora), puedo anular onBackPressed () y volver a la pantalla de inicio del dispositivo.

Luke Sleeman
fuente
1
solución alternativa, pero creo que es demasiado, para recrear miles de objetos solo para ocultar el teclado. No sé quién diseñó el IMM para Android, pero huele a un APi de Windows. En mi opinión, un buen IME debería tener dos métodos: ocultar y mostrar :-)
rompe
Todo es cierto, pero mi solución tiene una ventaja: ¡siempre funciona! No hay otra solución que pueda encontrar que siempre cambie el teclado, independientemente de qué campos en la interfaz de usuario tengan el foco, qué ha hecho el usuario para alternar y teclado y qué versión de Android están ejecutando: - \
Luke Sleeman
Hombre, estoy totalmente desesperado por ocultar el teclado. Probé miles de cosas y nadie trabaja. Pero su solución es demasiado para mí, tendría que recrear como 10 fragmentos, inicializar servicios, eliminar muchas referencias débiles ... ¿sabes? el GC simplemente tiraría como 25mb: S ... Todavía
estoy
@Dmitry bueno, no es un mundo hola ... es una aplicación compleja para tabletas. Me niego a descargarlo por completo de la memoria solo para ocultar un teclado tonto ... De todos modos, encontré algo que funciona combinando las mil soluciones propuestas aquí :)
rompe el
27

Alternativamente a esta solución completa , si desea cerrar el teclado virtual desde cualquier lugar sin tener una referencia al campo (Editar Texto) que se utilizó para abrir el teclado, pero aún así quería hacerlo si el campo estaba enfocado, podría usar esto (de una Actividad):

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

Gracias a esta respuesta SO , deduje lo siguiente que, en mi caso, funciona muy bien al desplazarse por los fragmentos de un 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);
    }
}
prohibición de geoingeniería
fuente
21

Las respuestas anteriores funcionan para diferentes escenarios, pero si desea ocultar el teclado dentro de una vista y lucha por obtener el contexto correcto, intente esto:

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

y para que el contexto lo obtenga del constructor :)

public View/RelativeLayout/so and so (Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.context = context;
    init();
}
Ash
fuente
18

Si desea cerrar el teclado virtual durante una unidad o prueba funcional, puede hacerlo haciendo clic en el "botón Atrás" de su prueba:

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

Pongo "botón de retroceso" entre comillas, ya que lo anterior no activa onBackPressed()la actividad en cuestión. Simplemente cierra el teclado.

Asegúrese de hacer una pausa por un momento antes de continuar, ya que lleva un poco de tiempo cerrar el botón Atrás, por lo que los clics posteriores a Vistas, etc., no se registrarán hasta después de una breve pausa (1 segundo es lo suficientemente largo )

Peter Ajtai
fuente
16

Así es como lo haces en Mono para Android (también conocido como MonoDroid)

InputMethodManager imm = GetSystemService (Context.InputMethodService) as InputMethodManager;
if (imm != null)
    imm.HideSoftInputFromWindow (searchbox.WindowToken , 0);
Ian Vink
fuente
1
¿Qué hay searchboxen el fragmento?
PCoder
16

Esto funcionó para mí por todo el extraño comportamiento del teclado

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
fuente
1
Creo que probé 10 respuestas antes de esta. Había perdido la esperanza. Gracias hombre.
Bolling
¿Qué es mRootView?
justdan0227
14

Agregue a su actividad android:windowSoftInputMode="stateHidden"en el archivo de manifiesto. Ejemplo:

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

Método simple y fácil de usar, solo llame a hideKeyboardFrom (YourActivity.this); para ocultar el teclado

/**
 * 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);
}
Naveed Ahmad
fuente
13

Simplemente use este código optimizado en su actividad:

if (this.getCurrentFocus() != null) {
    InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
    inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
Hamid FzM
fuente
Funciona bien. Gracias
Alif
12
public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

después de esa llamada en onTouchListener:

findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Utils.hideSoftKeyboard(activity);
        return false;
    }
});
Sagar Maiyad
fuente
Intente esto también, esto funcionó para mí: InputMethodManager imm = ((InputMethodManager) getSystemService (Activity.INPUT_METHOD_SERVICE)); imm.hideSoftInputFromWindow (getWindow (). getCurrentFocus (). getWindowToken (), 0);
zmicer
12

utilizar este

this.getWindow().setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Atish Agrawal
fuente
12

Para mi caso, estaba usando un SearchView en la barra de acción. Después de que un usuario realiza una búsqueda, el teclado se abriría nuevamente.

El uso de InputMethodManager no cerró el teclado. Tuve que borrar el enfoque y establecer el foco de la vista de búsqueda en falso:

mSearchView.clearFocus();
mSearchView.setFocusable(false);
tommy chheng
fuente
1
Muy inteligente. Si el usuario desea otra búsqueda, simplemente haga clic en buscar nuevamente.
Alex
SearchView no tiene un clearFocus()en las páginas de la API de Android, por lo que esto no funcionó para mí, pero otra solución sí (consulte mi respuesta a continuación).
Azurespot
@Noni A, stackoverflow.com/questions/7409288/…
Yousha Aleayoub
12

Tengo el caso, donde mi EditTextpuede ubicarse también en un AlertDialog, por lo que el teclado debe cerrarse al descartar. El siguiente código parece estar funcionando en cualquier lugar:

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 );
}
inyector
fuente
1
Esta solución es mejor porque no tiene que controlar qué EditText pasa como parámetro para ocultar el método hideSoftInputFromWindow (). ¡Funciona muy bien!
Billyjoker
12

Casi he probado todas estas respuestas, tuve algunos problemas al azar, especialmente con el Samsung Galaxy S5.

Lo que termino es forzar el espectáculo y esconderse, y funciona perfectamente:

/**
 * 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
fuente