2014-11-11 12 views
13

Ho utilizzato la libreria di supporto v7-21 e RecyclerView non viene visualizzato correttamente. GridLayoutManager e LinearLayoutManager è Ok. Il problema si verifica solo quando in StaggeredGridLayoutManager I Carico il mio DataSet e poi aggiorno i dati. L'aggiornamento dei dati sta funzionando bene ma la vista di RecyclerView esiste fuori dallo schermo.RecyclerView, StaggeredGridLayoutManager Aggiorna bug

qualcuno sa come risolverlo?

+1

stesso sta accadendo a me ... :( Lo StaggeredGridLayoutManager è buggy a partire da oggi ... – mato

risposta

9

Aggiornato 2015/01/04 (in basso)

Ho un progetto di esempio per dimostrare questo a https://github.com/dbleicher/recyclerview-grid-quickreturn. Ma ecco alcuni dettagli in più che potrebbero aiutarti.

Quando si aggiunge/rimuove un elemento in RecyclerView, è necessario chiamare notifyItemInserted/notifyItemRemoved per fare in modo che l'adattatore comunichi al gestore del layout di ridisporre solo le viste interessate. Per esempio, l'adattatore:

public void addItemAtPosition(int position, String item) { 
    myDataset.add(position, item); 
    mAdapter.notifyItemInserted(position);   
} 

Se si chiama questo metodo per aggiungere una vista, e la vista è su schermo, SGLM sembra funzionare come previsto inserimento e la regolazione del layout. Se, tuttavia, stai visualizzando la parte superiore dell'elenco e aggiungi l'elemento alla posizione zero, la vista viene creata fuori campo (e non la vedrai). È possibile scorrere a questa vista con questo codice seguente:

public void addItemAtPosition(int position, String item) { 
    myDataset.add(position, item); 
    mAdapter.notifyItemInserted(position); 
    mSGLM.scrollToPosition(position); 
} 

c'è (IMHO) un bug in StaggeredGridLayoutManager che si rivela con l'aggiunta di elementi "fuori dallo schermo". Secondo alle osservazioni di Yiğit boiardo in questa discussione https://plus.google.com/u/1/111532428576115387787/posts/6xxayUBz2iV

"... se un elemento viene aggiunto fuori limite, gestore di layout non si preoccupa"

Ed ecco dove appare il bug. Con SGLM, c'è un problema di temporizzazione con quando si verifica il nuovo layout. Nel mio codice di esempio (link sopra) ho un ItemDecorator che aggiunge margine agli elementi più in alto in modo che non siano oscurati dalla barra degli strumenti. Quando si utilizza il codice sopra, il layout mantiene questo margine in modo errato sull'elemento che viene spostato "in basso" sullo schermo quando vengono inseriti i nuovi articoli. Bummer.

Ecco il layout prima di aggiungere in cima: Layout before adding at top

Ecco il layout che dimostra il bug dopo l'aggiunta di un elemento in alto: Bad layout

c'è una soluzione, ma sconfigge in qualche modo lo scopo di usare un RecyclerView. Fondamentalmente, se si chiama notifyDataSetChanged dopo aver aggiunto/rimosso, questo farà sì che SGLM invalidi l'intero layout. Questo non è ottimale dal punto di vista dell'efficienza, ma risulta in un layout corretto. Utilizzando il codice seguente:

public void addItemAtPosition(int position, String item) { 
    myDataset.add(position, item); 
    mAdapter.notifyDataSetChanged(); // Should NOT do this, but it works! 
    mSGLM.scrollToPosition(position); 
} 

si tradurrà in una corretta, layout di post-addizione: Proper layout result

Spero che questo aiuti.

Aggiornamento: 2014-01-04

Come notato nei commenti, un'altra soluzione consiste nel chiamare invalidateItemDecorations() sul recyclerview dopo aver eseguito l'inserto. In questo momento, sembra che farlo immediatamente dopo l'inserimento ignorerà questa chiamata (probabilmente perché è già in esecuzione un passaggio di layout). Se si rinvia la chiamata brevemente, sembra funzionare:

public void addItemAtPosition(int position, String item) { 
    myDataset.add(position, item); 
    mAdapter.notifyItemInserted(position); 
    mSGLM.scrollToPosition(position); 

    // Items added to the top row? Better invalidate the decorator. 
    // Delay to ensure that the previous layout pass has completed. 
    if (position < columnCount) { 
     new Handler().postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       mRecycler.invalidateItemDecorations(); 
      } 
     }, 300); 
    } 
} 
+0

decorazioni Voce vengono memorizzati nella cache e quindi a meno che un elemento viene invalidata, non ci rebind. Si dovrebbe chiamare ' rv.invalidateItemDecorations'. – yigit

+0

Quando chiamo rv.invalidateItemDecorations() dopo aver inserito l'elemento, la chiamata viene ignorata perché (credo) sia già in corso un passaggio di layout dalla chiamata a notifyItemInserted.Se si ritarda la chiamata a invalidateItemDecorations (), questo funziona. Quindi, c'è ancora un problema di "timing" esattamente quando invalidare le decorazioni. – MojoTosh

0

Una soluzione semplice che ho trovato, è che si deve impostare nuovamente il gestore di layout quando si imposta l'adattatore per la visualizzazione riciclatore.

Problemi correlati