2014-11-11 4 views
13

Ich verwendete Support-Bibliothek v7-21 und die RecyclerView wird nicht korrekt angezeigt. GridLayoutManager und LinearLayoutManager ist Ok. Problem tritt nur auf, wenn in StaggeredGridLayoutManager I Laden Sie meine DataSet und aktualisieren Sie dann die Daten. Datenaktualisierung funktioniert gut, aber die RecyclerView Ansicht existiert außerhalb des Bildschirms.RecyclerView, StaggeredGridLayoutManager Aktualisieren Fehler

weiß jemand, wie man es repariert?

+1

Gleiche ist mir passiert ... :( Der StaggeredGridLayoutManager ist Buggy ab heute ... – mato

Antwort

9

Aktualisiert 2015.01.04 (unten)

Ich habe ein Beispielprojekt dies bei https://github.com/dbleicher/recyclerview-grid-quickreturn zu demonstrieren. Aber hier sind ein paar mehr Details, die Ihnen helfen können.

Wenn Sie ein Element zum RecyclerView hinzufügen/entfernen, sollten Sie notifyItemInserted/notifyItemRemoved aufrufen, damit der Adapter den Layout-Manager anweist, nur die betroffenen Ansichten neu zu strukturieren. Zum Beispiel in den Adapter:

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

Wenn Sie diese Methode aufrufen, eine Ansicht hinzuzufügen, und die Aussicht ist auf dem Bildschirm erscheint SGLM wie erwartet Einfügen arbeiten und das Layout anpassen. Wenn Sie jedoch den Anfang der Liste anzeigen und das Element an der Position Null hinzufügen, wird die Ansicht außerhalb des Bildschirms erstellt (und Sie werden es nicht sehen). Sie können mit diesem folgenden Code zu dieser Ansicht blättern:

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

Es gibt (IMHO) einen Fehler in StaggeredGridLayoutManager, die mit Hinzufügen von Elementen „off-screen“ offenbart. Nach Aussagen von yiğit Bojar in diesem Thread https://plus.google.com/u/1/111532428576115387787/posts/6xxayUBz2iV

„... wenn ein Element außerhalb der Grenzen hinzugefügt wird, Layout-Manager kümmert sich nicht darum“

Und hier ist, wo der Fehler angezeigt wird. Mit SGLM gibt es ein Timing-Problem mit , wenn das Re-Layout auftritt. In meinem Beispielcode (Link oben) habe ich einen ItemDecorator, der Rand zu den obersten Elementen hinzufügt, damit sie nicht von der Symbolleiste verdeckt werden. Wenn Sie den obigen Code verwenden, behält das Layout diesen Rand auf dem Objekt, das beim Einfügen der neuen Elemente auf den Bildschirm verschoben wird, fälschlicherweise bei. Bummel.

Hier ist das Layout vor an der Spitze hinzu: Layout before adding at top

Hier ist das Layout der Fehler nach dem Hinzufügen eines Elements an der Spitze zeigt: Bad layout

Es gibt eine Abhilfe, aber es Niederlagen etwas dem Zweck der Verwendung eines RecyclerView. Wenn Sie notifyDataSetChanged nur nach dem Hinzufügen/Entfernen aufrufen, wird SGLM das gesamte Layout ungültig machen. Dies ist aus Effizienzsicht nicht optimal, führt aber zu einem ordentlichen Layout. Mit dem folgenden Code: Proper layout result

this helps:

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

in dem richtigen, nachträgliche Zugabe Layout führen.

Update: 2014-01-04

Wie in den Kommentaren erwähnt, ist eine andere Abhilfe invalidateItemDecorations() auf der recyclerview aufzurufen, nachdem der Einsatz durchführen. Momentan scheint es, dass dies unmittelbar nach dem Einfügen ignoriert wird (möglicherweise weil ein Layout-Durchlauf bereits ausgeführt wird). Wenn man den Anruf kurz aufschiebt, es zu funktionieren scheint:

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

Artikel Dekorationen und zwischengespeichert werden, so dass, wenn ein Element für ungültig erklärt wird, werden wir es nicht erneut binden. Sie rufen sollte ' rv.invalidateItemDecorations'. – yigit

+0

Wenn ich nach dem Einfügen des Elements rv.invalidateItemDecorations() aufruft, wird der Aufruf ignoriert, weil (glaube ich) bereits ein Layoutdurchlauf vom Aufruf zu notifyItemInserted ausgeführt wird. Wenn man den Aufruf von invalidateItemDecorations verzögert (), funktioniert das. Es gibt also immer noch ein Problem mit dem "Timing", wann genau die Dekorationen ungültig gemacht werden sollen. – MojoTosh

0

Eine einfache Lösung, die ich gefunden, ist, dass Sie wieder den Layout-Manager einstellen, wenn Sie Adapter an die Recycler-Ansicht verwenden.