2008-11-02 11 views
101

Necesito averiguar la posición de píxeles de un elemento en una lista que se ha mostrado usando un ListView. Parece que debería obtener uno TextView y luego usar getTop(), pero no puedo entender cómo obtener una vista secundaria de un ListView.Android: Acceda a vistas secundarias desde un ListView

Actualización: Los hijos de la ViewGroup no corresponden 1-a-1 con los elementos de la lista, para un ListView. En cambio, los hijos de ViewGroup corresponden solo a las vistas que están visibles en este momento. Por lo tanto, getChildAt() opera en un índice que es interno al ViewGroup y no necesariamente tiene nada que ver con la posición en la lista que usa el ListView.

Respuesta

210

Ver: Android ListView: get data index of visible item y se combinan con parte de la respuesta de los pies por encima, le puede dar algo como:

int wantedPosition = 10; // Whatever position you're looking for 
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); // This is the same as child #0 
int wantedChild = wantedPosition - firstPosition; 
// Say, first visible position is 8, you want position 10, wantedChild will now be 2 
// So that means your view is child #2 in the ViewGroup: 
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) { 
    Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen."); 
    return; 
} 
// Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead. 
View wantedView = listView.getChildAt(wantedChild); 

La ventaja es que usted no está interactuando sobre los hijos del ListView, lo que podría tener un impacto en el rendimiento .

+10

Gran respuesta, pero no funciona bien cuando tiene vistas de encabezado en su lista. La asignación a 'firstPosition' debe ser' int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); 'para arreglar esto. – pospi

+0

@pospi: gracias, buen punto! He actualizado mi respuesta para dar cuenta de eso. – Joe

+33

¿Es usted un doctor? porque eres un salvavidas. –

5

Una búsqueda rápida de los documentos para la clase ListView ha resultado en métodos getChildCount() y getChildAt() heredados de ViewGroup. ¿Puedes iterar a través de ellos usando estos? No estoy seguro, pero vale la pena intentarlo.

encontrado que es here

+1

He intentado esto, para hacer selecciones. Por lo general, funciona, pero a veces hay errores de uno a uno y no es confiable. No lo recomendaría. – Timmmm

+0

Gracias Timmmm, no lo había intentado, solo lo encontré en los documentos. – Feet

-9

Esto supone que se conoce la posición del elemento en el ListView:

View element = listView.getListAdapter().getView(position, null, null); 

, entonces debería ser capaz de llamar a getLeft() y getTop() para determinar los elementos en posición de pantalla

+42

'getView()' es llamado internamente por ListView, al completar la lista. Usted * no debe * usarlo para obtener la vista en esa posición en la lista, ya que al llamar 'getView()' con nulo para 'convertView' hace que el adaptador infle una nueva vista desde el recurso de diseño del adaptador (no obtiene el vista que ya se está mostrando). – Joe

+2

¡Excelente punto! – jasonhudgins

+1

Incluso la posición será una posición en la pantalla visual, no en la posición de la fuente de datos del adaptador. – Vikas

15

Este código es más fácil de usar:

View rowView = listView.getChildAt(viewIndex);//The item number in the List View 
    if(rowView != null) 
     { 
      // Your code here 
     } 
+0

Esto funciona bien. No sé por qué tienes un voto negativo ... ¡voto popular! – Mark

+9

no funciona siempre. getChildAt cuenta desde la primera fila visible, no desde la parte superior de los datos. – SteelBytes

+13

El argumento ViewID es confuso. Es un índice (o posición). La ID de vista es un entero completamente arbitrario generado por la herramienta aapt. –

5
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { 

    @Override 
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) 
{  
    View v; 
    int count = parent.getChildCount(); 
    v =parent.getChildAt(position); 
    parent.requestChildFocus(v, view); v.setBackground(res.getDrawable(R.drawable.transparent_button)); 
      for (int i=0; i<count; i++) 
      { 
       if (i!= position) 
       { 
        v = parent.getChildAt(i);t v.setBackground(res.getDrawable(R.drawable.not_clicked)); 

       } 
      } 
     } 
    }); 

Básicamente, crear dos dibujables - uno que es transparente, y otro que es el color deseado. Solicitar enfoque en la posición cliqueada (posición int como se define) y cambiar el color de dicha fila. Luego camine a través del elemento primario listview y cambie todas las demás filas como corresponda. Esto cuenta cuando un usuario hace clic en listview varias veces. Esto se hace con un diseño personalizado para cada fila en el listview. (Muy sencillo, basta con un nuevo archivo de diseño con un textview - no establece enfocable o puede hacer clic!) No se requiere adaptador personalizado - adaptador de uso conjunto

+0

getChildAt es relativo a los elementos desplazados actuales. Esto dejará de funcionar si desplaza su lista solo un poco. – nurettin

4
int position = 0; 
listview.setItemChecked(position, true); 
View wantedView = adapter.getView(position, null, listview); 
+1

Elabora un poquito – innoSPG

+0

Dios te bendiga amigo, salva mi vida. – Euphor08

Cuestiones relacionadas