Wie aktualisiert man die angezeigten Daten RecyclerView
(ruft notifyDataSetChanged
den Adapter auf) und stellt sicher, dass die Bildlaufposition genau auf die Position zurückgesetzt wird, an der sie war?
Im Falle eines guten alten ist ListView
alles, was es braucht, abzurufen getChildAt(0)
, zu überprüfen getTop()
und anschließend setSelectionFromTop
mit denselben genauen Daten aufzurufen .
Im Falle von scheint es nicht möglich zu sein RecyclerView
.
Ich denke, ich sollte seine verwenden, LayoutManager
die zwar bietet scrollToPositionWithOffset(int position, int offset)
, aber wie kann man die Position und den Versatz richtig abrufen?
layoutManager.findFirstVisibleItemPosition()
und layoutManager.getChildAt(0).getTop()
?
Oder gibt es eine elegantere Möglichkeit, die Arbeit zu erledigen?
quelle
Antworten:
Ich benutze diesen. ^ _ ^
Es ist einfacher, hoffe es wird dir helfen!
quelle
Ich habe ein ziemlich ähnliches Problem. Und ich habe folgende Lösung gefunden.
Verwenden
notifyDataSetChanged
ist eine schlechte Idee. Sie sollten genauer sein und dannRecyclerView
den Bildlaufstatus für Sie speichern.Wenn Sie beispielsweise nur eine Aktualisierung benötigen oder mit anderen Worten möchten, dass jede Ansicht neu gebunden wird, gehen Sie wie folgt vor:
quelle
notifyDataSetChanged
eingefügt und mit der Bildlaufposition würde sich die Anzeige der neuen Elemente ändern. Wenn verwendet jedochnotifyItemRangeInserted(0, newItems.size() - 1)
dasRecyclerView
hält den Scroll - Zustand.BEARBEITEN: Um genau die gleiche scheinbare Position wie in wiederherzustellen , damit sie genau so aussieht wie sie, müssen wir etwas anderes tun (siehe unten, wie der genaue scrollY-Wert wiederhergestellt wird):
Speichern Sie die Position und den Versatz wie folgt:
Und stellen Sie dann die Schriftrolle wie folgt wieder her:
Dadurch wird die Liste an ihrer exakten scheinbaren Position wiederhergestellt . Anscheinend, weil es für den Benutzer gleich aussieht, aber nicht den gleichen scrollY-Wert hat (wegen möglicher Unterschiede in den Abmessungen des Quer- / Hochformat-Layouts).
Beachten Sie, dass dies nur mit LinearLayoutManager funktioniert.
--- Nachfolgend erfahren Sie, wie Sie den exakten Bildlauf wiederherstellen, wodurch die Liste wahrscheinlich anders aussieht ---
Wenden Sie einen OnScrollListener wie folgt an:
Dadurch wird die genaue Bildlaufposition jederzeit in mScrollY gespeichert.
Speichern Sie diese Variable in Ihrem Bundle und stellen Sie sie in der Statuswiederherstellung in einer anderen Variablen wieder her . Wir nennen sie mStateScrollY.
Nach der Wiederherstellung des Status und nachdem Ihr RecyclerView alle Daten zurückgesetzt hat, setzen Sie den Bildlauf folgendermaßen zurück:
Das ist es.
Beachten Sie, dass Sie den Bildlauf in einer anderen Variablen wiederherstellen. Dies ist wichtig, da der OnScrollListener mit .scrollBy () aufgerufen wird und anschließend mScrollY auf den in mStateScrollY gespeicherten Wert setzt. Wenn Sie dies nicht tun, hat mScrollY den doppelten Bildlaufwert (da der OnScrollListener mit Deltas arbeitet, nicht mit absoluten Bildläufen).
Staatliche Einsparungen bei Aktivitäten können wie folgt erreicht werden:
Und um es wiederherzustellen, rufen Sie dies in Ihrem onCreate () auf:
Das Speichern von Zuständen in Fragmenten funktioniert auf ähnliche Weise, aber das Speichern von Zuständen erfordert ein wenig zusätzliche Arbeit, aber es gibt viele Artikel, die sich damit befassen. Sie sollten also kein Problem damit haben, herauszufinden, wie die Prinzipien zum Speichern des scrollY funktionieren und die Wiederherstellung bleiben gleich.
quelle
Ja, Sie können dieses Problem beheben, indem Sie den Adapterkonstruktor nur einmal erstellen. Ich erkläre den Codierungsteil hier:
Jetzt können Sie sehen, dass ich überprüft habe, ob der Adapter null ist oder nicht, und erst initialisiere, wenn er null ist.
Wenn der Adapter nicht null ist, kann ich sicher sein, dass ich meinen Adapter mindestens einmal initialisiert habe.
Also werde ich einfach eine Liste zum Adapter hinzufügen und notifydatasetchanged aufrufen.
RecyclerView hält immer die letzte gescrollte Position, daher müssen Sie nicht die letzte Position speichern. Rufen Sie einfach notifydatasetchanged auf. Die Recycler-Ansicht aktualisiert immer Daten, ohne nach oben zu gehen.
Vielen Dank Happy Coding
quelle
Behalten Sie die Bildlaufposition bei, indem Sie die Antwort @DawnYu verwenden, um
notifyDataSetChanged()
wie folgt zu verpacken :quelle
Die Top-Antwort von @DawnYu funktioniert, aber die Recycling-Ansicht scrollt zuerst nach oben und kehrt dann zur beabsichtigten Scroll-Position zurück, was zu einer "flimmerartigen" Reaktion führt, die nicht angenehm ist.
Um die recyclerView zu aktualisieren, insbesondere nachdem Sie von einer anderen Aktivität gekommen sind, ohne zu flackern und die Bildlaufposition beizubehalten, müssen Sie die folgenden Schritte ausführen.
Hoffe das hilft.
quelle
Ich habe Recyclerview nicht verwendet, aber ich habe es in ListView gemacht. Beispielcode in Recyclerview:
Es ist der Listener, wenn der Benutzer einen Bildlauf durchführt. Der Leistungsaufwand ist nicht signifikant. Und die erste sichtbare Position ist auf diese Weise genau.
quelle
findFirstVisibleItemPosition
gibt "die Adapterposition der ersten sichtbaren Ansicht" zurück, aber was ist mit dem Versatz?Die Lösung hier besteht darin, die Recycling-Ansicht weiter zu scrollen, wenn eine neue Nachricht eingeht.
Die onChanged () -Methode erkennt die in recyclerview ausgeführte Aktion.
quelle
Das funktioniert bei mir in Kotlin.
Der Bildlaufversatz ändert sich nicht.
quelle
Ich hatte dieses Problem mit einer Liste von Elementen, die jeweils eine Zeit in Minuten hatten, bis sie "fällig" waren und aktualisiert werden mussten. Ich würde die Daten aktualisieren und danach anrufen
und es würde jedes Mal nach oben scrollen. Ich habe das durch ersetzt
und es war in Ordnung. Keine der anderen Methoden in diesem Thread hat bei mir funktioniert. Bei Verwendung dieser Methode wurde jedoch jedes einzelne Element beim Aktualisieren blinken gelassen, sodass ich dies auch in die onCreateView des übergeordneten Fragments einfügen musste
quelle
Wenn Sie einen oder mehrere EditTexts in einem Recyclerview-Element haben, deaktivieren Sie den Autofokus dieser Elemente und fügen Sie diese Konfiguration in die übergeordnete Ansicht von recyclerview ein:
Ich hatte dieses Problem, als ich eine andere Aktivität startete, die von einem Recyclerview-Element aus gestartet wurde. Als ich zurückkam und eine Aktualisierung eines Felds in einem Element mit notifyItemChanged (Position) festlegte, bewegt sich der Bildlauf von RV, und meine Schlussfolgerung war, dass der Autofokus von EditText Artikel, der obige Code hat mein Problem gelöst.
Beste.
quelle
Kehren Sie einfach zurück, wenn die alte Position und Position identisch sind.
quelle