Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Problema de enfoque con múltiples EditTexts

Tengo una actividad con dos EditText s. Estoy llamando el requestFocus en el segundo campo EditText ya que por defecto el foco va al primero. El foco parece estar en el segundo campo (el segundo recibe el borde resaltado), pero si intentamos introducir cualquier carácter usando el teclado del hardware, el texto aparece en el primer control EditText . ¿Alguna idea de por qué sucedería?

  • Cómo puedo fijar el foco (y exhibir el teclado) en mi EditText programmatically
  • Problema de enfoque de Android WebView
  • Cambiar el enfoque a EditarTexto Android
  • Amplíe y dé enfoque a SearchView automáticamente
  • Android: ¿Para establecer un elemento como seleccionado cuando se abre ListView?
  • Detener ScrollView de establecer el enfoque en EditText
  • No se puede administrar a requestFocus a Spinner
  • EditText, foco claro en el tacto afuera
  • 4 Solutions collect form web for “Problema de enfoque con múltiples EditTexts”

    Es difícil saber si este fue tu problema, pero no es improbable.

    TL; DR: Nunca llame a métodos de cambio de foco como requestFocus() desde dentro de una llamada onFocusChanged() .

    El problema reside en ViewGroup.requestChildFocus() , que contiene lo siguiente:

     // We had a previous notion of who had focus. Clear it. if (mFocused != child) { if (mFocused != null) { mFocused.unFocus(); } mFocused = child; } 

    Dentro del campo privado mFocused un ViewGroup almacena la vista secundaria que actualmente tiene el foco, si la hay.

    Digamos que tiene un ViewGroup VG que contiene tres vistas seleccionables (por ejemplo, EditTexts) A , B y C

    Has agregado un OnFocusChangeListener a A que (tal vez no directamente, pero en algún lugar anidado dentro) llama B.requestFocus() cuando A pierde el foco.

    Ahora imagine que A tiene enfoque, y el usuario teclea en C , haciendo que A pierda y C gane foco. Debido a que VG.mFocused es actualmente A , la parte anterior de VG.requestChildFocus(C, C) se traduce a esto:

     if (A != C) { if (A != null) { A.unFocus(); // <-- (1) } mFocused = C; // <-- (3) } 

    A.unFocus() hace dos cosas importantes aquí:

    1. Marca A como no tener foco más.

    2. Llama a su oyente de cambio de enfoque.

    En ese oyente, ahora llamas B.requestFocus() . Esto hace que B se marque como teniendo foco y, a continuación, llama a VG.requestChildFocus(B, B) . Debido a que todavía estamos dentro de la llamada que he marcado con (1) , el valor de mFocused sigue siendo A , y por lo tanto esta llamada interna tiene este aspecto:

     if (A != B) { if (A != null) { A.unFocus(); } mFocused = B; // <-- (2) } 

    Esta vez, la llamada a A.unFocus() no hace nada, ya que A ya está marcado como desenfocado (de lo contrario tendríamos una recursión infinita aquí). Además, no pasa nada que señale a C como desenfocado, que es el punto de vista que en realidad se centra ahora mismo.

    Ahora viene (2) , que establece mFocused a B Después de algunas cosas más, finalmente regresamos de la llamada en (1) , y por lo tanto en (3) el valor de mFocused ahora se establece en C , sobrescribiendo el cambio anterior .

    Así que ahora terminamos con un estado incosistente. B y C piensan que tienen foco, VG considera que C es el niño enfocado.

    En particular, las pulsaciones de tecla terminan en C , y es imposible para el usuario cambiar el enfoque de nuevo a B , ya que B piensa que ya tiene foco y por lo tanto no hace nada en las solicitudes de enfoque; Lo más importante, no llama a VG.requestChildFocus .

    Corolario: También no debe confiar en los resultados de las llamadas hasFocus() mientras está dentro de un controlador OnFocusChanged , porque la información de enfoque es inconsistente mientras está dentro de esa llamada.

    Encontré la solución.

    Dentro de onFocusChange no llamar directamente requestFocus, en lugar de publicar un runnable para solicitar el enfoque. Por ejemplo debajo de mi código,

     editText.setOnFocusChangeListener(new OnFocusChangeListener() { public void onFocusChange(View v, boolean hasFocus) { if (hasFocus == false) { editText.post(new Runnable() { @Override public void run() { editText.requestFocus(); } }); } } }); 

    Me enfrenté al mismo problema, uno de mis EditText tiene un OnFocusListener y cuando se pierde el foco hago algunas transformaciones, pero si algo va mal, intento requestFocus de nuevo y dejar que el usuario solucione el problema. Aquí es cuando el problema aparece, termino con EditText con el enfoque, traté de buscar la vista con el enfoque, pero el findFocus () devuelto null. La única solución que encontré fue crear una variable EditText

     private EditText requestFocus; 

    Si cualquier problema, fijé mi EditText a esa variable y aquí es lo que no me gusta pero trabaja, fijé OnFocusListener a las otras vistas en mi actividad. Cuando ganan el foco, hago esto

     @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) if(requestFocus != null){ v.clearFocus(); requestFocus.requestFocus(); requestFocus = null; } } 

    Quito el foco de la vista que lo tiene, solicito Focus y configuro la variable requestFocus null.

    Creo que esto está sucediendo porque en el momento en que solicito un foco nadie tiene un foco todavía, mi EditText recuperar el foco y la actividad da el foco a la vista siguiente. Espero que ayude a alguien.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.