2010-06-09 21 views
14

Tengo una actividad con dos EditText s. Estoy llamando al requestFocus en el segundo campo EditText ya que de manera predeterminada el foco va al primero. El foco parece estar en el segundo campo (el segundo tiene el borde resaltado), pero si tratamos de ingresar cualquier carácter usando el teclado de hardware, el texto aparece en el primer control EditText. ¿Alguna idea de por qué estaría sucediendo?Problema de enfoque con múltiples EditTexts

+2

Por favor, publique su código para que podamos ver exactamente lo que está haciendo. – Harris

+0

Sin más información, esta pregunta no puede responderse de manera razonable, y se ha mantenido sin información adicional durante bastante tiempo. –

Respuesta

1

Me enfrenté al mismo problema, uno de mis EditText tiene un OnFocusListener y cuando pierde el foco, realizo algunas transformaciones, pero si algo sale mal, intento solicitar nuevamente el botón y dejar que el usuario solucione el problema. Aquí es cuando aparece el problema, termino con EditText con foco, traté de buscar en la vista con el foco pero el findFocus() devolvió nulo. La única solución que encontré fue la de crear una variable EditarTexto

private EditText requestFocus; 

Si cualquier problema, puse mis EditarTexto a esa variable y esto es lo que no me gusta, pero funciona, me puse OnFocusListener a los otros puntos de vista sobre mi actividad. Cuando ganan enfoque, hago esto

@Override 
public void onFocusChange(View v, boolean hasFocus) { 

    if (hasFocus) 
     if(requestFocus != null){ 
      v.clearFocus(); 
      requestFocus.requestFocus(); 
      requestFocus = null; 
     } 
} 

¿Está claro el enfoque desde el punto de vista que lo tiene, solicito enfocar y ajustar la nula requestFocus variable.

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

19

Es difícil saber si este fue su problema, pero no es poco probable.

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

El problema radica 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 ámbito privado mFocused una tiendas ViewGroup la vista del niño que está seleccionado actualmente, en su caso.

Digamos que tienes una ViewGroup VG que contiene tres vistas enfocable (por ejemplo EditTexts) A, B y C.

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

Ahora imagina que A tiene enfoque, y el usuario toca C, causando que A pierda y C para enfocar.Debido VG.mFocused es actualmente A, la parte anterior de VG.requestChildFocus(C, C) luego 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 enfoque más.

  2. Llama a su oyente de cambio de enfoque.

En ese oyente, ahora llama al B.requestFocus(). Esto ocasiona que B se marque como que tiene foco, y luego llama al VG.requestChildFocus(B, B). Debido a que estamos todavía en el interior de la llamada He marcado con (1), el valor de mFocused sigue siendo A, y por lo tanto esta llamada interior se parece a esto:

if (A != B) { 
    if (A != null) { 
     A.unFocus(); 
    } 

    mFocused = B;    // <-- (2) 
} 

Esta vez, la llamada a A.unFocus() no lo hace hacer cualquier cosa, porque A ya está marcado como desenfocado (de lo contrario, tendremos aquí una recursión infinita). Además, no ocurre nada que marque C como desenfocado, que es la vista que actualmente tiene foco en este momento.

Ahora viene (2), que establece mFocused en B. Después de algunas cosas más, finalmente regresamos de la llamada al (1), y así 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 ambos piensan que tienen foco, VG considera que C es el niño enfocado.

En particular, las pulsaciones de teclas terminan en C, y es imposible que el usuario cambie de nuevo a centrarse B, porque B piensa que ya tiene el foco y por lo tanto no hace nada en las solicitudes de enfoque; lo más importante, lo hace no llamada VG.requestChildFocus.

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

+0

respuesta increíble ... mi problema era algo similar a esto ... votaciones en contra –

+1

Gran respuesta, pero ¿qué recomiendas para evitar esto? Solo publique un mensaje para hacerlo? –

+0

@RossHambrick Sí, tienes que estar fuera del controlador de eventos, así que esa es realmente la única solución que se me ocurre. – balpha

4

Encontré la solución.

Inside onFocusChange no llame directamente requestFocus, en su lugar publique un ejecutable para solicitar el enfoque. p.ej. 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(); 
         } 
        }); 
      } 
     } 
    }); 
+0

No hizo diferencia en mi caso. – Tomislav3008

+0

@ Tomislav3008 ¿Por qué no creas una pregunta con un código que muestra lo que estás intentando, entonces puedo ayudarte? –

+0

Logré poner el foco de mi solicitud fuera del controlador focusChange, que es el camino a seguir. El problema que tuve fue exactamente lo que balpha explicó, obteniendo dos vistas de edición de texto con ambos teniendo foco. Tal vez mi problema fue ponerlo en un controlador en lugar de un oyente, donde tuve '((EditText) remitente) .Post (nuevo Runnable (delegar {((EditText) remitente) .RequestFocus();}));' – Tomislav3008

Cuestiones relacionadas