2010-11-02 26 views
39

¿Es posible volver a dibujar una sola fila en un ListView? Tengo un ListView con filas que son LinearLayout s. Escucho un cambio de preferencia y, a veces, necesito cambiar solo un View dentro del LinearLayout de una sola fila. ¿Hay alguna manera de hacerlo volver a dibujar esa fila sin llamar al listview.notifyDatasetChanged()?Redibujar una sola fila en una vista de lista

He intentado llamar a view.invalidate() en la vista (dentro del LinearLayout) pero no vuelve a dibujar la fila.

+1

"¿Hay alguna manera de volver a dibujar esa fila sin llamar a listview.notifydatasetchanged()?" - Simplemente búscalo como un elemento secundario del 'ViewGroup' (en este caso,' ListView') y modifícalo. "Intenté llamar a view.invalidate() en la vista (dentro de linearlayout) pero no vuelve a dibujar la fila". - ¿Estás seguro de que tienes la fila correcta? Ni siquiera debería necesitar llamar 'invalidate()', AFAIK. – CommonsWare

+1

Definitivamente tengo la fila correcta y la vista correcta. Creo que mi problema es que mi oyente de preferencia es basura. Lo cambié, así que llamé a notifyDataSetChanged() en onResume() de mi actividad, que resuelve el problema que estaba tratando de corregir. – Falmarri

Respuesta

105

Como Romain individuo explained a while espalda durante el Google I/O session, la forma más eficiente para actualizar un único punto de vista en una vista de lista es algo así como lo siguiente (éste actualizar el conjunto View datos):

ListView list = getListView(); 
int start = list.getFirstVisiblePosition(); 
for(int i=start, j=list.getLastVisiblePosition();i<=j;i++) 
    if(target==list.getItemAtPosition(i)){ 
     View view = list.getChildAt(i-start); 
     list.getAdapter().getView(i, view, list); 
     break; 
    } 

Suponiendo target es un elemento del adaptador.

Este código de recuperar el ListView, a continuación, busque los puntos de vista que se muestran actualmente, comparar el elemento target que busca con cada muestra la vista elementos, y si su objetivo es entre aquellos, obtener la vista de cerramiento y ejecutar el adaptador getView() en ese ver para actualizar la pantalla.

Como nota al margen invalidate() no funciona igual que algunas personas que esperan y no actualizar la vista como getView() hace, notifyDataSetChanged() reconstruirá toda la lista y terminan llamando getview() por cada elementos que se muestran y invalidateViews() también afectará a un montón.

Una última cosa, uno también puede obtener un rendimiento adicional si solo necesita cambiar un elemento secundario de una vista de fila y no toda la fila como getView.En ese caso, el siguiente código puede reemplazar list.getAdapter().getView(i, view, list); (ejemplo para cambiar un texto TextView):

((TextView)view.findViewById(R.id.myid)).setText("some new text"); 

en código confiamos.

+0

¿Podría agregar un enlace a la sesión de Google I/O? Quiero verificar toda la sesión. – uthark

+0

+1 thx para esto, es interesante - estoy suponiendo que funciona como pasar la vista actual como convertView arg y tendrá sus elementos de vista restablecer - muy bien – Dori

+0

No debería ser aquí i

0

Ponga una etiqueta en la fila que desea actualizar. Cuando desee volver a dibujar ese punto de vista o una fila específica a continuación, hacer

ListView lv = (ListView)findViewById(....) 

y luego

View v = lv.findViewWithTag(tagobject); 

y luego hacer lo que quieras con la vista.

6

El view.invalidate() no funcionó para mí. Pero esto funciona como un encanto:

Supongamos que está actualizando la posición "position" en la fila. El if evita elementos extraños para volver a dibujar, como el texto bailando cuando está actualizando una fila que no está en la pantalla.

  if (position >= listView.getFirstVisiblePosition() 
       && position <= listView.getLastVisiblePosition()) { 

        runOnUiThread(new Runnable() { 
         @Override 
         public void run() { 
          listView.invalidateViews(); 
         } 
        }); 
      } 
+1

Está funcionando amigo :) pero parece recrear todas las filas ... ¿alguna forma de recrear una sola fila? –

3

Romain individuo respondió a esta cuestión en "Google OI 2010 El mundo de ListView" vídeo en el momento exacto en el que se hizo esta pregunta: http://www.youtube.com/watch?feature=player_detailpage&v=wDBM6wVEO70#t=3149s

Así que de acuerdo a Romain individuo, que debe trabajar, y creo que podemos confiar en él.

La razón por la cual su vista no se vuelve a dibujar es un tanto misteriosa. Tal vez pruebe a desactivar todas las opciones de caché disponible en Listview

setAnimationCacheEnabled(false); 
setScrollingCacheEnabled(false); 
setChildrenDrawingCacheEnabled(false); 
setChildrenDrawnWithCacheEnabled(false); 
+1

Esto no es lo que dijo. Dijo que el método getView aún se llamará, pero al generar el ui, el motor puede ver que los datos de los elementos no han cambiado, y luego los está reutilizando. –

Cuestiones relacionadas