2012-07-04 3 views
5

In Gingerbread non ho riscontrato problemi con l'uso di smoothScrollToPosition() per scorrere decine di elementi alla volta. Dopo che il mio Nexus S è stato aggiornato a Ice Cream Sandwich, ho notato che, indipendentemente da ciò che ho inserito in smoothScrollToPosition(), scorrerà solo per un paio di centinaia di pixel in entrambe le direzioni, quindi si fermerà.smoothScrollToPosition() scorre solo parzialmente su Android ICS?

Si tratta di un problema noto con ICS? L'ho notato anche con il Galaxy Nexus. Ho esaminato alcune altre domande e ho provato alcuni trucchi diversi, come disattivare le chiamate a notifyDataSetChanged(), e postare smoothScrollToPosition() come eseguibile in ritardo, ma sfortunatamente, non si vuole scorrere più di un cento pixel circa prima di fermarsi. :(

+2

Ho lo stesso problema. http://code.google.com/p/android/issues/detail?id=37278 – bigstones

+1

Ho postato lì una soluzione alternativa. – bigstones

+0

Sembra risolto in Jellybean. –

risposta

12

Sembra essere un problema con la durata richiesta per terminare l'animazione, lo stesso problema è presente con smoothScrollBy (int distance, int duration), a colpo d'occhio scorciatoie, smoothScrollToPosition() è un involucro amichevole intorno smoothScrollBy() smoothScrollBy() a sua volta sta simulando un "gesto di lancio", come se un utente avesse fatto il movimento

smoothScrollBy posta davvero solo il runnable di lanci che continua a ripubblicarsi fino a che la durata non viene eseguita Out. Significa che calcola semplicemente l'offset di scorrimento richiesto in base all'offset su cui aveva deciso di spostarsi, quindi se la durata si esaurisce prima che arrivi all'offset target, si arresta all'ultimo offset calcolato (piuttosto che tutto il salto improvviso). all'offset target, che è perhap s più sconcertante in quanto non sarebbe animato).

La difficoltà per i ragazzi Android è determinare quanto spostare ciascuna chiamata run() per raggiungere l'offset richiesto perché le celle ListView (bambini) sono completamente dinamiche in altezza, quindi non possono semplicemente eseguire un calcolo a distanza semplice poiché l'altezza dei bambini non visibili è sconosciuta a loro. È lo stesso motivo per cui la barra di scorrimento Android può fluttuare di dimensioni mentre si scorre, deve fare una stima migliore di quanto dovrebbe essere grande in base a ciò che sta attualmente vedendo.

In ogni caso, che non aiuta a risolverlo, ma qualcuno potrebbe trovare interessante :)

Se sai di avere l'altezza delle celle statiche tuttavia, è possibile scrivere il proprio metodo per calcolare la distanza e la durata di passare per smoothScrollBy() e avere una quantità di tempo statica per spostare la distanza X. In caso contrario, sarà necessario utilizzare la soluzione bigstones pubblicata, che funziona davvero a causa dell'elevata SCROLL_DURATION di 1000 ms. Puoi prendere la versione di ICS e cambiare questo attributo, piuttosto che usare la versione 2.2, che non è la causa principale.

È anche possibile adattare questi runnables con il proprio algoritmo personalizzato, non dovrebbe essere troppo difficile modificare le cose.

0

Poiché ListView utilizza il metodo getChildCount() per ottenere il conteggio della posizione nel codice sorgente AbsListView.java. ma in ListView il metodo getChildCount() non può ottenere il conteggio corretto. Forse dovresti usare il metodo setSelection().

2

Questo è quello che ho fatto per risolvere il problema. In sostanza, vogliamo continuare a chiamare smoothscrolling fino a raggiungere l'elemento desiderato (in questo caso, voglio semplicemente scorrere verso l'alto, che è l'elemento 0).

//There is a known bug where smoothScrollToPosition(..) may not reach the top, 
      //if the list is very large, keep scrolling until you reach the top element 
      newsFeed.setOnScrollListener(new OnScrollListener() { 
       @Override 
       public void onScrollStateChanged(AbsListView view, int scrollState) { 

       } 

       @Override 
       public void onScroll(AbsListView view, int firstVisibleItem, 
         int visibleItemCount, int totalItemCount) { 
        if(firstVisibleItem != 0) { 
         newsFeed.smoothScrollToPosition(0); 
        } 
        else { 
         //We are done 
         newsFeed.setOnScrollListener(null); 
        } 
       } 
      }); 
      newsFeed.smoothScrollToPosition(0); 
0

Ho un problema anche su ICS.

Ho un'attività di elenco dei messaggi di chat, ogni volta che ho inviato il messaggio, ho bisogno di scorrere il listview fino in fondo senza problemi. Quindi, dopo aver chiamato notifyDataSetChanged(), ho chiamato il metodo smoothScrollToPosition(). Su altre versioni di build Android, funziona bene. Ma su ICS, è molto strano. Se il mio listview è in fondo, ho testato 3 casi.se aggiungo un nuovo oggetto a listview, non scorrerà. Se aggiungo due nuovi elementi alla vista elenco -> scorrerà bene. E se faccio scorrere la lista con alcuni pixes, dopo aver aggiunto un nuovo elemento, scorrerà bene. Dopo un sacco di ricerche su google e test, mi sento impotente a questo. Alla fine, ogni volta che setdata per listview, aggiungo una vista vuota (1px) nell'ultima posizione, anche se questo non è un buon metodo, ma funziona per me.

2

Se il tuo obiettivo è quello di scorrere verso l'alto, considera l'utilizzo di smoothScrollToPositionFromTop(0,0). anziché.