studio quitar how edittext change android focus android-edittext

android - quitar - quit focus edittext



EditText, claro foco en el tacto afuera (13)

Basándose en la respuesta de Ken, esta es la solución más modular de copiar y pegar.

No se necesita XML.

Colóquelo en su Actividad y se aplicará a todos los EditTexts, incluidos aquellos dentro de los fragmentos dentro de esa actividad.

@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())) { v.clearFocus(); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } } } return super.dispatchTouchEvent( event ); }

Mi diseño contiene ListView , SurfaceView y EditText . Cuando hago clic en EditText , recibe el foco y aparece el teclado en pantalla. Cuando hago clic en algún lugar fuera de EditText , todavía tiene el foco (no debería). Creo que podría configurar OnTouchListener en las otras vistas en el diseño y borrar manualmente el EditText de EditText . Pero parece demasiado hackish ...

También tengo la misma situación en el otro diseño: vista de lista con diferentes tipos de elementos, algunos de los cuales tienen dentro EditText . Actúan justo como escribí arriba.

La tarea es hacer que EditText pierda el foco cuando el usuario toca algo fuera de él.

He visto preguntas similares aquí, pero no he encontrado ninguna solución ...


Como @pcans sugirió que puede hacer esto reemplazando dispatchTouchEvent(MotionEvent event) en su actividad.

Aquí obtenemos las coordenadas táctiles y las comparamos para ver los límites. Si el toque se realiza fuera de una vista, entonces haz algo.

@Override public boolean dispatchTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { View yourView = (View) findViewById(R.id.view_id); if (yourView != null && yourView.getVisibility() == View.VISIBLE) { // touch coordinates int touchX = (int) event.getX(); int touchY = (int) event.getY(); // get your view coordinates final int[] viewLocation = new int[2]; yourView.getLocationOnScreen(viewLocation); // The left coordinate of the view int viewX1 = viewLocation[0]; // The right coordinate of the view int viewX2 = viewLocation[0] + yourView.getWidth(); // The top coordinate of the view int viewY1 = viewLocation[1]; // The bottom coordinate of the view int viewY2 = viewLocation[1] + yourView.getHeight(); if (!((touchX >= viewX1 && touchX <= viewX2) && (touchY >= viewY1 && touchY <= viewY2))) { Do what you want... // If you don''t want allow touch outside (for example, only hide keyboard or dismiss popup) return false; } } } return super.dispatchTouchEvent(event); }

Además, no es necesario verificar la visibilidad y visibilidad de la vista si el diseño de su actividad no cambia durante el tiempo de ejecución (por ejemplo, no agrega fragmentos ni reemplaza / elimina vistas del diseño). Pero si desea cerrar (o hacer algo similar) el menú contextual personalizado (como en Google Play Store cuando usa el menú de desbordamiento del elemento), es necesario verificar la existencia de la vista. De lo contrario, obtendrás una NullPointerException .


Intenté todas estas soluciones. El de edc598 fue el más cercano al trabajo, pero los eventos táctiles no se activaron en otras View encuentran en el diseño. En caso de que alguien necesite este comportamiento, esto es lo que terminé haciendo:

FrameLayout FrameLayout (invisible) llamado touchInterceptor como la última View en el diseño para que se superponga todo ( edit: también tienes que usar un RelativeLayout como el diseño principal y otorgar los atributos touchInterceptor fill_parent ). Luego lo usé para interceptar toques y determinar si el toque estaba sobre EditText o no:

FrameLayout touchInterceptor = (FrameLayout)findViewById(R.id.touchInterceptor); touchInterceptor.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (mEditText.isFocused()) { Rect outRect = new Rect(); mEditText.getGlobalVisibleRect(outRect); if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) { mEditText.clearFocus(); InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } } } return false; } });

Devuelve falso para permitir que la manipulación táctil se caiga.

Es hacky, pero es lo único que funcionó para mí.


La mejor forma es usar el método predeterminado clearFocus()

¿Sabes cómo resolver códigos en el onTouchListener verdad?

Simplemente llame a EditText.clearFocus() . last EditText foco en el last EditText .


La respuesta de Ken funciona, pero es hacky. Como pcans alude en el comentario de la respuesta, lo mismo podría hacerse con dispatchTouchEvent. Esta solución es más limpia ya que evita tener que hackear el XML con FrameLayout ficticio transparente. Esto es lo que parece:

@Override public boolean dispatchTouchEvent(MotionEvent event) { EditText mEditText = findViewById(R.id.mEditText); if (event.getAction() == MotionEvent.ACTION_DOWN) { View v = getCurrentFocus(); if (mEditText.isFocused()) { Rect outRect = new Rect(); mEditText.getGlobalVisibleRect(outRect); if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) { mEditText.clearFocus(); // // Hide keyboard // InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } } } return super.dispatchTouchEvent(event); }


Para la vista principal de EditText, permita que los siguientes 3 atributos sean " verdaderos ":
hacer clic , enfocable , enfocableInTouchMode .

Si una vista desea recibir el foco, debe cumplir estas 3 condiciones.

Ver android.view :

public boolean onTouchEvent(MotionEvent event) { ... if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) { ... if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { focusTaken = requestFocus(); } ... } ... }

Espero eso ayude.


Para mí, debajo de las cosas trabajadas:

1. Agregando android:clickable="true" y android:focusableInTouchMode="true" al parentLayout de EditText es decir android.support.design.widget.TextInputLayout

<android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:clickable="true" android:focusableInTouchMode="true"> <EditText android:id="@+id/employeeID" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:inputType="number" android:hint="Employee ID" tools:layout_editor_absoluteX="-62dp" tools:layout_editor_absoluteY="16dp" android:layout_marginTop="42dp" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:layout_marginRight="36dp" android:layout_marginEnd="36dp" /> </android.support.design.widget.TextInputLayout>

2. Reemplazando dispatchTouchEvent en la clase Activity e insertando la función hideKeyboard()

@Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { View view = getCurrentFocus(); if (view != null && view instanceof EditText) { Rect r = new Rect(); view.getGlobalVisibleRect(r); int rawX = (int)ev.getRawX(); int rawY = (int)ev.getRawY(); if (!r.contains(rawX, rawY)) { view.clearFocus(); } } } return super.dispatchTouchEvent(ev); } public void hideKeyboard(View view) { InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); }

3. Agregando setOnFocusChangeListener para EditText

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



Probablemente ya hayas encontrado la respuesta a este problema, pero he estado buscando cómo resolverlo y todavía no puedo encontrar exactamente lo que estaba buscando, así que pensé en publicarlo aquí.

Lo que hice fue lo siguiente (esto es muy generalizado, el propósito es darte una idea de cómo proceder, copiar y pegar todo el código no funcionará O: D):

Primero tiene el EditText y cualquier otra vista que desee en su programa envuelto por una sola vista. En mi caso, utilicé LinearLayout para envolver todo.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/mainLinearLayout"> <EditText android:id="@+id/editText"/> <ImageView android:id="@+id/imageView"/> <TextView android:id="@+id/textView"/> </LinearLayout>

Luego, en su código, debe configurar un Listener Touch en su LinearLayout principal.

final EditText searchEditText = (EditText) findViewById(R.id.editText); mainLinearLayout.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub if(searchEditText.isFocused()){ if(event.getY() >= 72){ //Will only enter this if the EditText already has focus //And if a touch event happens outside of the EditText //Which in my case is at the top of my layout //and 72 pixels long searchEditText.clearFocus(); InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } } Toast.makeText(getBaseContext(), "Clicked", Toast.LENGTH_SHORT).show(); return false; } });

Espero que esto ayude a algunas personas. O al menos les ayuda a comenzar a resolver su problema.


Realmente creo que es una forma más sólida de usar getLocationOnScreen que getGlobalVisibleRect . Porque encuentro un problema. Hay una vista de lista que contiene algún texto de edición y establece ajustpan en la actividad. Encuentro que getGlobalVisibleRect devuelve un valor que parece incluir el desplazamiento Y en él, pero event.getRawY siempre está en la pantalla. El siguiente código funciona bien.

public boolean dispatchTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { View v = getCurrentFocus(); if ( v instanceof EditText) { if (!isPointInsideView(event.getRawX(), event.getRawY(), v)) { Log.i(TAG, "!isPointInsideView"); Log.i(TAG, "dispatchTouchEvent clearFocus"); v.clearFocus(); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } } } return super.dispatchTouchEvent( event ); } /** * Determines if given points are inside view * @param x - x coordinate of point * @param y - y coordinate of point * @param view - view object to compare * @return true if the points are within view bounds, false otherwise */ private boolean isPointInsideView(float x, float y, View view) { int location[] = new int[2]; view.getLocationOnScreen(location); int viewX = location[0]; int viewY = location[1]; Log.i(TAG, "location x: " + location[0] + ", y: " + location[1]); Log.i(TAG, "location xWidth: " + (viewX + view.getWidth()) + ", yHeight: " + (viewY + view.getHeight())); // point is inside view bounds return ((x > viewX && x < (viewX + view.getWidth())) && (y > viewY && y < (viewY + view.getHeight()))); }


Simplemente defina dos propiedades de parent de ese EditText como:

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

Por lo tanto, cuando el usuario toque fuera del área EditText , el enfoque se eliminará porque el enfoque se transferirá a la vista principal.


Simplemente ponga estas propiedades en la parte superior del padre.

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


Tengo un ListView compuesto por vistas de EditText . El escenario dice que después de editar el texto en una o más filas, debemos hacer clic en un botón llamado "finalizar". onFocusChanged en la vista EditText dentro de listView pero después de hacer clic en finish no se guardan los datos. El problema fue resuelto agregando

listView.clearFocus();

dentro de onClickListener para el botón "finalizar" y los datos se guardaron con éxito.