2010-11-02 6 views
39

È possibile ridisegnare una singola riga in un ListView? Ho un ListView con righe che sono LinearLayout s. Ascolto un cambio di preferenza e talvolta devo modificare solo uno View all'interno dello LinearLayout di una singola riga. C'è un modo per farlo ridisegnare quella riga senza chiamare listview.notifyDatasetChanged()?Ridisegna una singola riga in una listview

Ho provato a chiamare view.invalidate() sulla vista (all'interno dello LinearLayout) ma non ridisegna la riga.

+1

"C'è un modo per farlo ridisegnare quella riga senza chiamare listview.notifydatasetchanged()?" - basta trovarlo come figlio del 'ViewGroup' (in questo caso,' ListView') e modificarlo. "Ho provato a chiamare view.invalidate() sulla vista (all'interno del linearlayout) ma non ridisegna la riga." - sei sicuro di avere la fila giusta? Non dovresti nemmeno aver bisogno di chiamare 'invalidate()', AFAIK. – CommonsWare

+1

Ho sicuramente la fila giusta e la vista giusta. Penso che il mio problema è che il mio ascoltatore di preferenze è quello di raccogliere i rifiuti. L'ho cambiato, così chiamo notifyDataSetChanged() nella mia attività suResume(), che risolve il problema che stavo cercando di risolvere. – Falmarri

risposta

105

Come Romain Guy explained a while schiena durante la Google I/O session, il modo più efficiente per aggiornare solo una vista in una vista lista è qualcosa di simile alla seguente (questo aggiornare l'intera View dati):

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; 
    } 

Supponendo target è un elemento della scheda.

Questo codice recuperare la ListView, quindi visualizza le viste attualmente indicati, confrontare la voce target siete alla ricerca di uno con l'visualizzate le voci vista, e se il vostro obiettivo è tra quelli, ottenere la vista che racchiude ed eseguire l'adattatore getView() su quel visualizza per aggiornare il display.

Come nota a margine invalidate() non funziona come alcune persone si aspettano e non saranno aggiornare la vista come getView() fa, notifyDataSetChanged() sarà ricostruire l'intera lista e finiscono per chiamare getview() ogni elementi visualizzati e invalidateViews() influirà anche un mazzo.

Un'ultima cosa, si può anche ottenere prestazioni extra se ha solo bisogno di cambiare una vista figlio di una riga e non l'intera riga come getView.In tal caso, il seguente codice può sostituire list.getAdapter().getView(i, view, list); (esempio per cambiare un testo TextView):

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

Nel codice ci fidiamo.

+0

Potresti aggiungere il link alla sessione di I/O di Google? Voglio controllare l'intera sessione. – uthark

+0

+1 thx per questo, è interessante - presumo che funzioni come passare la vista corrente come convertView arg e avrà i suoi elementi di visualizzazione ripristinati - molto bello – Dori

+0

Non dovrebbe essere qui

0

Inserire un tag sulla riga che si desidera aggiornare. Quando si desidera ridisegnare quella vista o riga specifica poi fare

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

e poi

View v = lv.findViewWithTag(tagobject); 

e poi fare quello che vuoi con la vista.

6

Il view.invalidate() non ha funzionato per me. Ma questo funziona come un fascino:

supponiamo che stai aggiornando la posizione "position" nella riga. Il if evita oggetti di ridisegno strani, come la danza del testo quando si è l'aggiornamento di una riga che non è nella schermata.

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

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

È un tipo di lavoro :) ma sembra ricreare tutte le righe ... un modo per ricreare una singola riga ?? –

3

Romain Guy ha risposto a questa domanda in "Google IO 2010 Il mondo di ListView" video nel momento esatto in cui questa domanda è stato chiesto: http://www.youtube.com/watch?feature=player_detailpage&v=wDBM6wVEO70#t=3149s

Quindi, secondo Romain Guy, che dovrebbe funzionare, e penso che possiamo fidarci di lui.

Il motivo per cui la visualizzazione non è ridisegnata è un po 'misteriosa. Forse provare a disattivare tutte le opzioni di cache disponibile in listView

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

Questo non è quello che ha detto. Ha detto che il metodo getView sarà ancora chiamato, ma quando genera l'interfaccia utente il motore può vedere che i dati degli articoli non sono cambiati e li sta riutilizzando. –