Cómo ocultar el teclado de software en Android después de hacer clic fuera de EditText?


Ok todo el mundo sabe que para ocultar un teclado es necesario implementar:

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

Pero el gran problema aquí es cómo ocultar el teclado cuando el usuario toca o selecciona cualquier otro lugar que no sea un EditText o el softKeyboard?

Traté de usar el onTouchEvent() en mi padre Activity pero eso solo funciona si el usuario toca fuera de cualquier otra vista y no hay scrollview.

Traté de implementar un toque, haga clic, enfoque oyente sin ningún éxito.

Incluso traté de implementar mi propio scrollview para interceptar eventos táctiles, pero solo puedo obtener las coordenadas del evento y no la vista pulsada.

¿Hay una forma estándar de hacer esto?? en iPhone fue muy fácil.

Author: Gowtham Subramaniam, 2010-11-12

30 answers

El siguiente fragmento simplemente oculta el teclado:

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

Puede poner esto en una clase de utilidad, o si lo está definiendo dentro de una actividad, evite el parámetro activity, o llame a hideSoftKeyboard(this).

La parte más difícil es cuándo llamarlo. Puede escribir un método que itere a través de cada View en su actividad, y comprobar si es un instanceof EditText si no es registrar un setOnTouchListener a ese componente y todo se caerá en su lugar. En caso de que se pregunte cómo hacer eso, está en hecho bastante simple. Esto es lo que haces, escribes un método recursivo como el siguiente, de hecho puedes usar esto para hacer cualquier cosa, como configurar tipos de letra personalizados, etc... Aquí está el método

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

Eso es todo, simplemente llame a este método después de setContentView en su actividad. En caso de que se pregunte qué parámetro pasaría, es el id del contenedor padre. Asigna un id a tu contenedor padre como

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

Y llama setupUI(findViewById(R.id.parent)), eso es todo.

Si si desea usar esto de manera efectiva, puede crear un Activity extendido y poner este método, y hacer que todas las demás actividades de su aplicación extiendan esta actividad y llamen a su setupUI() en el método onCreate().

Espero que ayude.

Si usa más de 1 actividad, defina el id común para el diseño principal como <RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>

Luego extienda una clase desde Activity y defina setupUI(findViewById(R.id.main_parent)) Dentro de su OnResume() y extienda esta clase en lugar de " Actividad in your program

 516
Author: Navneeth G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-29 14:57:54

Puede lograr esto haciendo los siguientes pasos:

  1. Haga que la vista padre(vista de contenido de su actividad) se pueda hacer clic y enfocar agregando los siguientes atributos

        android:clickable="true" 
        android:focusableInTouchMode="true" 
    
  2. Implementar un método hideKeyboard ()

        public void hideKeyboard(View view) {
            InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    
  3. Por último, establezca el OnFocusChangeListener de su edittext.

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

Como se señala en uno de los comentarios a continuación, esto podría no funcionar si la vista padre es una vista de desplazamiento. Para tal caso, el clickable y focusableInTouchMode se pueden agregar en la vista directamente debajo de ScrollView.

 216
Author: vida,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-11 16:20:04

Encuentro la respuesta aceptada un poco complicada.

Aquí está mi solución. Agregue un OnTouchListener a su diseño principal, es decir.:

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

Y poner el siguiente código en el método onTouch.

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

De esta manera no tiene que iterar sobre todas las vistas.

 47
Author: roepit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-02 14:25:04

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

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

Aquí pase HIDE_IMPLICIT_ONLY en la posición de showFlag y 0 en la posición de hiddenFlag. Se cerrará con fuerza el teclado de software.

 35
Author: Saurabh Pareek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-20 07:38:11

Bueno, me las arreglo para resolver un poco el problema, anulé el dispatchTouchEvent en mi actividad, allí estoy usando lo siguiente para ocultar el teclado.

 /**
 * 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: El método GetFields() es solo un método que devuelve un array con los textfields en la vista. Para evitar crear esta matriz en cada toque, he creado una matriz estática llamada sFields, que se devuelve en el método GetFields (). Esta matriz se inicializa en los métodos onStart () tales as:

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


No es perfecto, el tiempo del evento de arrastre solo se basa en la heurística, por lo que a veces no se oculta al realizar clics largos, y también terminé creando un método para obtener todos los EditTexts por vista; de lo contrario, el teclado se ocultaría y se mostraría al hacer clic en otro EditText.

Aún así, las soluciones más limpias y más cortas son bienvenidas

 16
Author: htafoya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-01 14:26:57

Use OnFocusChangeListener.

Por ejemplo:

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

Actualizar : también puedes anular onTouchEvent() en tu actividad y comprobar las coordenadas del toque. Si las coordenadas están fuera de EditText, oculte el teclado.

 12
Author: Sergey Glotov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-12 14:48:00

Implementé dispatchTouchEvent en la actividad para hacer esto:

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

Y lo probé, funciona perfecto!

 11
Author: Jishi Chen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-24 11:25:42

Override public boolean dispatchTouchEvent (evento MotionEvent) en cualquier Actividad (o extender clase de actividad)

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

Y eso es todo lo que necesitas hacer

 10
Author: Hoang Trinh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-27 13:21:23

Soy consciente de que este hilo es bastante viejo, la respuesta correcta parece válida y hay un montón de soluciones de trabajo por ahí, pero creo que el enfoque que se indica a continuación podría tener un beneficio adicional con respecto a la eficiencia y la elegancia.

Necesito este comportamiento en todas mis actividades, así que he creado una clase CustomActivity heredando de la clase Actividad y "enganchado" el dispatchTouchEvent function. Hay principalmente dos condiciones para tener cuidado de:

  1. Si el foco no cambia y alguien está tocando fuera del campo de entrada actual, entonces deseche el IME
  2. Si el foco ha cambiado y el siguiente elemento enfocado no es una instancia de ningún tipo de campo de entrada, entonces deseche el IME

Este es mi resultado:

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

Nota al margen: Además, asigno estos atributos a la vista raíz, lo que permite despejar el foco en cada campo de entrada y evitar que los campos de entrada se concentren en el inicio de la actividad (haciendo que la vista de contenido sea el "receptor de enfoque"):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final View view = findViewById(R.id.content);

    view.setFocusable(true);
    view.setFocusableInTouchMode(true);
}
 9
Author: fje,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-23 18:11:43

Modifiqué la solución de André Luis IM Logré esta:

Creé un método de utilidad para ocultar el teclado de software de la misma manera que Andre Luiz IM lo hizo:

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

Pero en lugar de registrar un OnTouchListener para cada vista, que da un rendimiento pobre, registré el OnTouchListener solo para la vista raíz. Desde que el evento aparece en burbujas hasta que se consume (EditText es una de las vistas que lo consume de forma predeterminada), si llega a la vista raíz, es porque no se consumió, así que cierro el teclado.

findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Utils.hideSoftKeyboard(activity);
        return false;
    }
});
 7
Author: Fernando Camargo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-12 20:01:35

Me gustó el enfoque de llamar dispatchTouchEvent hecho por htafoya, pero:

  • No entendí la parte del temporizador (¿no sé por qué debería ser necesario medir el tiempo de inactividad?)
  • No me gusta registrar / anular el registro de todos los EditTexts con cada cambio de vista (podría ser una gran cantidad de viewchanges y edittexts en jerarquías complejas)

Así que hice esta solución algo más fácil:

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

Hay una desventaja:

Cambiando de uno EditText a otro EditText hace que el teclado se oculte y vuelva a mostrar - en mi caso se desea de esa manera, porque muestra que ha cambiado entre dos componentes de entrada.

 5
Author: Christian R.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-20 00:00:27

Súplica: Reconozco que no tengo influencia, pero por favor toma mi respuesta en serio.

Problema: Descartar el teclado de software al hacer clic fuera del teclado o editar texto con un código mínimo.

Solución: Biblioteca externa conocida como Butterknife.

Solución de una línea:

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

Solución más legible:

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

Explicación: Enlaza el oyente OnClick al ID principal de diseño XML de la actividad, de modo que cualquier clic en el diseño (no en el texto de edición o teclado) ejecutará ese fragmento de código que ocultará el teclado.

Ejemplo: Si su archivo de diseño es R. layout. my_layout y su id de diseño es R. id. my_layout_id, entonces su llamada de enlace Butterknife debería tener el siguiente aspecto:

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

Enlace a la Documentación de Butterknife: http://jakewharton.github.io/butterknife /

Plug: Butterknife revolucionará su desarrollo de Android. Considerar se.

Nota: El mismo resultado se puede lograr sin el uso de la biblioteca externa Butterknife. Simplemente establezca un OnClickListener en el diseño padre como se describió anteriormente.

 4
Author: Charles Woodson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-30 15:09:05

Método para mostrar / ocultar el teclado de software

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

    }

Espero que hayan sido útiles

 3
Author: lalosoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-10 18:43:37

Aquí hay otra variación de la respuesta de fje que aborda las cuestiones planteadas por sosite.

La idea aquí es manejar tanto las acciones hacia abajo como hacia arriba en el método dispatchTouchEvent de la Actividad. En la acción hacia abajo, tomamos nota de la vista actualmente enfocada (si la hay) y si el toque estaba dentro de ella, guardando ambos bits de información para más adelante.

En la acción up, primero despachamos, para permitir que otra vista se enfoque potencialmente. Si después de eso, la vista actualmente enfocada es la vista originalmente enfocada, y el toque hacia abajo estaba dentro de esa vista, luego dejamos el teclado abierto.

Si la vista actualmente enfocada es diferente de la vista originalmente enfocada y es un EditText, entonces también dejamos el teclado abierto.

De lo contrario lo cerramos.

Así que, para resumir, esto funciona de la siguiente manera: {[14]]}

  • al tocar dentro de un EditText actualmente enfocado, el teclado permanece abierto
  • al pasar de un centrado EditText a otro EditText, el teclado permanece abierto (no se cierra/vuelve a abrir)
  • al tocar en cualquier lugar fuera de un EditText actualmente enfocado que no es otro EditText, el teclado se cierra
  • cuando se presiona durante mucho tiempo en un EditText para mostrar la barra de acciones contextuales (con los botones cortar/copiar/pegar), el teclado permanece abierto, a pesar de que la acción hacia ARRIBA tuvo lugar fuera del EditText enfocado (que se movió hacia abajo para hacer espacio para la CABINA). Tenga en cuenta, sin embargo, que cuando toque un botón en la cabina, se cerrará el teclado. Eso puede o no ser deseable; si desea cortar/copiar de un campo y pegar a otro, lo sería. Si desea pegar de nuevo en el mismo EditText, no sería.
  • Cuando el EditText enfocado está en la parte inferior de la pantalla y hace un largo clic en algún texto para seleccionarlo, el EditText mantiene el enfoque y, por lo tanto, el teclado se abre como desee, porque hacemos la verificación "touch is within view bounds" en la acción hacia abajo, no en la acción hacia arriba.

    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);
    }
    
 3
Author: Andy Dennie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-24 20:27:25

Es demasiado simple, simplemente haga que su diseño reciente se pueda hacer clic y se pueda enfocar con este código:

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

Y luego escriba un método y un OnClickListner para ese diseño , de modo que cuando el diseño superior se toque en cualquier lugar, llamará a un método en el que escribirá código para descartar el teclado. el siguiente es el código para ambos; // tienes que escribir esto en onCreate ()

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

Método llamado desde listner: -

 public void hideKeyboard(View view) {
     InputMethodManager imm =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }
 3
Author: swarnim dixit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-20 10:52:43

Hay un enfoque más simple, basado en iPhone mismo problema. Simplemente anule el diseño del fondo en el evento touch, donde se encuentra el texto de edición. Simplemente use este código en el onCreate de la actividad (login_fondo es el diseño raíz):

    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;
                }
            });
 2
Author: Alex R. R.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-12 08:53:32

He refinado el método, poner el siguiente código en alguna clase de utilidad de interfaz de usuario(preferiblemente, no necesariamente) para que se pueda acceder desde todas sus clases de Actividad o Fragmento para servir a su propósito.

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

Luego digamos, por ejemplo, que necesita llamarlo desde la actividad, llámelo de la siguiente manera;

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

Aviso

FindViewById(android.R.id.content)

Esto nos da la vista raíz del grupo actual(no debe haber establecido el id en la raíz vista).

Saludos:)

 2
Author: Uzair,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-22 06:46:19

Intente poner stateHidden como su actividad windowSoftInputMode valor

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

Por ejemplo para su Actividad:

this.getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
 2
Author: Alex Volovoy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-20 07:33:31

Actividad

 @Override
 public boolean dispatchTouchEvent(MotionEvent ev) {
     ScreenUtils.hideKeyboard(this, findViewById(android.R.id.content).getWindowToken());
     return super.dispatchTouchEvent(ev);
 }

ScreenUtils

 public static void hideKeyboard(Context context, IBinder windowToken) {
     InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
     imm.hideSoftInputFromWindow(windowToken, InputMethodManager.HIDE_NOT_ALWAYS);
 }
 2
Author: icebail,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-01 13:39:32

A más Kotlin & Material Design way usando TextInputEditText (este enfoque también es compatible con EditTextView )...

1.Haga que la vista principal(vista de contenido de su actividad/fragmento) se pueda hacer clic y enfocar agregando los siguientes atributos

android:focusable="true"
android:focusableInTouchMode="true"
android:clickable="true"

2.Cree una extensión para toda la vista (dentro de una ViewExtension.archivo kt por ejemplo):

fun View.hideKeyboard(){
    val inputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    inputMethodManager.hideSoftInputFromWindow(this.windowToken, 0)
}

3.Cree un BaseTextInputEditText que herede TextInputEditText. Implementar el método onFocusChanged para ocultar el teclado cuando la vista no está enfocada:

class BaseTextInputEditText(context: Context?, attrs: AttributeSet?) : TextInputEditText(context, attrs){
    override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect)
        if (!focused) this.hideKeyboard()
    }
}

4.Simplemente llame a su nueva vista personalizada en su XML:

<android.support.design.widget.TextInputLayout
        android:id="@+id/textInputLayout"
        ...>

        <com.your_package.BaseTextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            ... />

    </android.support.design.widget.TextInputLayout> 

Eso es todo. No es necesario modificar sus controladores (fragmento o actividad) para manejar este caso repetitivo.

 2
Author: Phil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-01 08:37:38

Encuentro complejo el bit de respuesta aceptado para este simple requisito. Esto es lo que funcionó para mí sin ningún problema.

findViewById(R.id.mainLayout).setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
            return false;
        }
    });
 2
Author: Joohay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-20 13:59:22

Esto puede ser viejo, pero tengo esto trabajando mediante la implantación de una clase personalizada

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

La mejor práctica aquí es crear una clase Helper y cada Disposición Relativa / Lineal de contenedor debería implementarla.

* * * * Tome nota de que solo el Contenedor principal debe implementar esta clase (Para la optimización) * * * *

E implementarlo así:

Parent.setOnClickListener( new DismissKeyboardListener(this) ); 

La palabra clave esto es para Actividad. así que si estás en fragment utilizas como getActivity();

- - - pulgar hacia arriba si ayuda usted... --- salud Ralph- - -

 1
Author: ralphgabb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-17 03:16:25

Esta es una versión ligeramente modificada de la respuesta de fje que en su mayoría funcionó perfectamente.

Esta versión utiliza ACTION_DOWN por lo que realizar una acción de desplazamiento también cierra el teclado. Tampoco propaga el evento a menos que haga clic en otro EditText. Esto significa que al hacer clic en cualquier lugar fuera de su EditText, incluso en otro en el que se puede hacer clic, simplemente se cierra el teclado.

@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);
}
 1
Author: Cadmonkey33,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-14 23:39:49

He hecho esto:

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

Ocultar código de teclado :

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

Hecho

 1
Author: Hiren Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-01 13:49:07

Para resolver este problema lo que tienes que hacer es primero usar setOnFocusChangeListener de ese 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");
                }
            }
        });

Y luego lo que necesita hacer es anular dispatchTouchEvent en la actividad que contiene ese Edittext ver código a continuación

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

Ahora lo que sucederá es que cuando un usuario haga clic fuera, primero se llamará a este dispatchTouchEvent, que luego borrará el enfoque del editext ahora se llamará a su OnFocusChangeListener. puede hacer cualquier cosa que usted quería hacer espero que funcione

 1
Author: Sudhanshu Gaur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-04 19:41:22
@Override
    public boolean onTouchEvent(MotionEvent event) {
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.
                INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
        return true;
    }
 1
Author: Jeffy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-03 17:56:26

Otra idea es anular el método onInterceptTouchEvent en la vista raíz de su Actividad.

El evento táctil va desde la vista frontal más en la pantalla (donde se produjo el evento táctil) hasta la pila de vistas que llaman al método onTouch hasta que cualquiera de las vistas devuelva true, lo que indica que el evento táctil se consumió. Como muchas de las vistas consumen el evento táctil de forma predeterminada (es el caso de EditText o TextView, por ejemplo), el evento no llega a la vista raíz de la Actividad onTouch método.

Pero, antes de hacer este recorrido, el evento touch recorre otro camino, yendo desde la vista raíz por el árbol de vistas hasta llegar a la vista más frontal. Este recorrido se realiza llamando a onInterceptTouchEvent. Si el método devuelve true, intercepta el evento... nahhh, pero eso es un pequeño truco, no creo que quieras hacer eso ni saber los detalles. Lo que necesita saber es que puede anular este método en la vista raíz de su actividad, y poner allí el código para ocultar el teclado cuando sea necesario.

 0
Author: Andre Luis IM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-12 14:59:47

Tengo esto trabajando con una ligera variante de la solución de Fernando Camarago. En mi método onCreate adjunto un único OnTouchListener a la vista raíz, pero envío la vista en lugar de la actividad como argumento.

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

En una clase Utils separada es...

    public static void hideSoftKeyboard(View v) {
    InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 
    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
 0
Author: AndyMc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-04 16:48:53

Puede anular fácilmente el evento onKey() en activity y fragments para ocultar el teclado.

@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;
}
 0
Author: Ajith Memana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-13 08:14:11

Hey chicos tengo una solución simple para este problema y esta solución se puede utilizar para el registro simple o formulario de inicio de sesión. mi solución es la misma que implementé en ios setontouch listener a la vista principal

Activity_main.xml añadir ID a su diseño relativo principal android:id="@+id/mainlayout"

Y añade este código a tu actividad

  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;
            }
        });
 0
Author: Swap-IOS-Android,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-28 11:11:29