EditText enfocable dentro de ListView

Resuelto Joe asked hace 54 años • 13 respuestas

He pasado aproximadamente 6 horas en esto hasta ahora y no he encontrado nada más que obstáculos. La premisa general es que hay alguna fila en un ListView(ya sea generada por el adaptador o agregada como una vista de encabezado) que contiene un EditTextwidget y un archivo Button. Todo lo que quiero hacer es poder usar el jogball/flechas para navegar el selector a elementos individuales como de costumbre, pero cuando llego a una fila en particular, incluso si tengo que identificar explícitamente la fila, esa tiene un enfoque enfocable. niño, quiero que ese niño se enfoque en lugar de indicar la posición con el selector.

He probado muchas posibilidades y hasta ahora no he tenido suerte.

disposición:

<ListView
    android:id="@android:id/list" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent"
    />

Vista de encabezado:

EditText view = new EditText(this);
listView.addHeaderView(view, null, true);

Suponiendo que hay otros elementos en el adaptador, el uso de las teclas de flecha moverá la selección hacia arriba o hacia abajo en la lista, como se esperaba; pero al llegar a la fila del encabezado, también se muestra con el selector y no hay forma de concentrarse en el EditTextuso del jogball. Nota: al tocar, EditText se enfocará en ese punto; sin embargo, eso depende de una pantalla táctil, lo cual no debería ser un requisito.

ListViewaparentemente tiene dos modos a este respecto:
1 setItemsCanFocus(true).: el selector nunca se muestra, pero EditTextpuede enfocarse cuando se usan las flechas. El algoritmo de búsqueda de enfoque es difícil de predecir y no hay información visual (en ninguna fila: tener hijos enfocables o no) sobre qué elemento se selecciona, lo cual puede brindarle al usuario una experiencia inesperada.
2.: setItemsCanFocus(false)el selector siempre se dibuja en modo no táctil y EditTextnunca puede enfocarse, incluso si lo tocas.

Para empeorar las cosas, la llamada editTextView.requestFocus()devuelve verdadero, pero en realidad no da el foco EditarTexto.

Lo que estoy imaginando es básicamente un híbrido de 1 y 2, donde en lugar de configurar la lista si todos los elementos son enfocables o no, quiero establecer la capacidad de enfoque para un solo elemento en la lista, de modo que el selector pase sin problemas de seleccionar el fila completa para elementos que no se pueden enfocar y atravesar el árbol de enfoque para elementos que contienen elementos secundarios que se pueden enfocar.

¿Ningún arrendatario?

Joe avatar Jan 01 '70 08:01 Joe
Aceptado

Esto me ayudó.
En su manifiesto:

<activity android:name= ".yourActivity" android:windowSoftInputMode="adjustPan"/>
logan avatar Feb 04 '2011 18:02 logan

Lo siento, respondí mi propia pregunta. Puede que no sea la solución más correcta ni la más elegante, pero a mí me funciona y ofrece una experiencia de usuario bastante sólida. Miré el código de ListView para ver por qué los dos comportamientos son tan diferentes y encontré esto en ListView.java:

    public void setItemsCanFocus(boolean itemsCanFocus) {
        mItemsCanFocus = itemsCanFocus;
        if (!itemsCanFocus) {
            setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
        }
    }

Entonces, al llamar setItemsCanFocus(false), también establece la capacidad de enfoque descendiente de modo que ningún niño pueda concentrarse. Esto explica por qué no podía simplemente alternar mItemsCanFocusel OnItemSelectedListener de ListView, porque ListView estaba bloqueando el foco para todos los niños.

Lo que tengo ahora:

<ListView
    android:id="@android:id/list" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent"
    android:descendantFocusability="beforeDescendants"
    />

Lo uso beforeDescendantsporque el selector solo se dibujará cuando el ListView en sí (no un hijo) tenga el foco, por lo que el comportamiento predeterminado debe ser que ListView se enfoque primero y dibuje los selectores.

Luego, en OnItemSelectedListener, como sé qué vista de encabezado quiero anular el selector (se necesitaría más trabajo para determinar dinámicamente si una posición determinada contiene una vista enfocable), puedo cambiar la capacidad de enfoque descendiente y establecer el enfoque en EditText. Y cuando salgo de ese encabezado, lo cambio nuevamente.

public void onItemSelected(AdapterView<?> listView, View view, int position, long id)
{
    if (position == 1)
    {
        // listView.setItemsCanFocus(true);

        // Use afterDescendants, because I don't want the ListView to steal focus
        listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        myEditText.requestFocus();
    }
    else
    {
        if (!listView.isFocused())
        {
            // listView.setItemsCanFocus(false);

            // Use beforeDescendants so that the EditText doesn't re-take focus
            listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
            listView.requestFocus();
        }
    }
}

public void onNothingSelected(AdapterView<?> listView)
{
    // This happens when you start scrolling, so we need to prevent it from staying
    // in the afterDescendants mode if the EditText was focused 
    listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
}

Tenga en cuenta las llamadas comentadas setItemsCanFocus. Con esas llamadas, obtuve el comportamiento correcto, pero setItemsCanFocus(false)hice que el foco saltara de EditText a otro widget fuera de ListView, regresara a ListView y mostrara el selector en el siguiente elemento seleccionado, y ese salto de foco distraía. Eliminar el cambio de ItemsCanFocus y simplemente alternar la capacidad de enfoque descendiente me dio el comportamiento deseado. Todos los elementos dibujan el selector como de costumbre, pero al llegar a la fila con EditText, se centró en el campo de texto. Luego, al continuar con ese EditText, comenzó a dibujar el selector nuevamente.

Joe avatar Apr 21 '2010 03:04 Joe

Mi tarea era implementar ListViewque se expande cuando se hace clic. El espacio adicional muestra EditTextdónde puede ingresar texto. La aplicación debe funcionar en 2.2+ (hasta 4.2.2 al momento de escribir esto)

Probé numerosas soluciones de esta publicación y otras que pude encontrar; Los probé en dispositivos 2.2 hasta 4.2.2. Ninguna de las soluciones fue satisfactoria en todos los dispositivos 2.2+, cada solución presentaba problemas diferentes.

Quería compartir mi solución final:

  1. establecer vista de lista enandroid:descendantFocusability="afterDescendants"
  2. establecer vista de lista ensetItemsCanFocus(true);
  3. configure su actividad como android:windowSoftInputMode="adjustResize" Mucha gente sugiere, adjustPanpero adjustResizeofrece una experiencia de usuario mucho mejor en mi humilde opinión, simplemente pruebe esto en su caso. Con esto adjustPanobtendrás los elementos de la lista inferior oscurecidos, por ejemplo. Los documentos sugieren que ("Esto es generalmente menos deseable que cambiar el tamaño"). También en 4.0.4, después de que el usuario comienza a escribir en el teclado virtual, la pantalla se desplaza hacia la parte superior.
  4. en 4.2.2 adjustResizehay algunos problemas con el enfoque de EditText. La solución es aplicar la solución rjrjr de este hilo. Parece aterrador pero no lo es. Y funciona. Solo inténtalo.

Adicional 5. Debido a que el adaptador se actualiza (debido al cambio de tamaño de la vista) cuando EditTextlas ganancias se centran en las versiones anteriores a HoneyComb, encontré un problema con las vistas invertidas: obtener la vista para el elemento ListView/orden inverso en 2.2; funciona en 4.0.3

Si está haciendo algunas animaciones, es posible que desee cambiar el comportamiento adjustPande las versiones anteriores al panal para que el cambio de tamaño no se active y el adaptador no actualice las vistas. Solo necesitas agregar algo como esto

if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

Todo esto proporciona una experiencia de usuario aceptable en dispositivos 2.2 - 4.2.2. Espero que le ahorre algo de tiempo a la gente, ya que me llevó al menos varias horas llegar a esta conclusión.

AndroidGecko avatar Apr 04 '2013 18:04 AndroidGecko

Esto me salvó la vida--->

  1. establecer esta línea

    ListView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

  2. Luego, en su manifiesto en la etiqueta de actividad, escriba esto-->

    <activity android:windowSoftInputMode="adjustPan">

Tu intención habitual

ravi ranjan avatar Oct 18 '2015 16:10 ravi ranjan