Ich habe eine lange Zeit ListView
, die der Benutzer scrollen kann, bevor er zum vorherigen Bildschirm zurückkehrt. Wenn der Benutzer dies ListView
erneut öffnet , soll die Liste an den gleichen Punkt gescrollt werden, an dem sie zuvor war. Irgendwelche Ideen, wie dies erreicht werden kann?
android
android-listview
scroll
scroll-position
Rantravee
quelle
quelle
Antworten:
Versuche dies:
Erläuterung:
ListView.getFirstVisiblePosition()
Gibt das oberste sichtbare Listenelement zurück. Dieses Element wird jedoch möglicherweise teilweise nicht mehr angezeigt. Wenn Sie die genaue Bildlaufposition der Liste wiederherstellen möchten, müssen Sie diesen Versatz abrufen. SoListView.getChildAt(0)
gibt dasView
für das Top-Listenelement, und dannView.getTop() - mList.getPaddingTop()
kehrt die relative von der Spitze des OffsetListView
. Um die Bildlaufposition des Elements wiederherzustellenListView
, rufen wirListView.setSelectionFromTop()
mit dem Index des gewünschten Elements und einem Versatz auf, um dessen Oberkante von der Oberseite des Elements zu positionierenListView
.quelle
int index = mList.getFirstVisiblePosition();
und nur eine Zeile zum Wiederherstellen :mList.setSelectionFromTop(index, 0);
. Tolle Antwort (+1)! Ich habe nach einer eleganten Lösung für dieses Problem gesucht.quelle
Ich habe die von @ (Kirk Woll) vorgeschlagene Lösung übernommen und sie funktioniert für mich. Ich habe auch im Android-Quellcode für die "Kontakte" -App gesehen, dass sie eine ähnliche Technik verwenden. Ich möchte noch einige Details hinzufügen: Oben in meiner von ListActivity abgeleiteten Klasse:
Dann überschreibt eine Methode:
Natürlich ist "loadData" meine Funktion, um Daten aus der Datenbank abzurufen und in die Liste aufzunehmen.
Auf meinem Froyo-Gerät funktioniert dies sowohl, wenn Sie die Ausrichtung des Telefons ändern, als auch wenn Sie ein Element bearbeiten und zur Liste zurückkehren.
quelle
mListState = getListView().onSaveInstanceState().
Hauptsächlich bei Gerätedrehung nicht erstellt wird.onRestoreInstanceState
wird nie genannt :(Ein sehr einfacher Weg:
Die Methode setSelection setzt die Liste auf das angegebene Element zurück. Wenn sich das Objekt nicht im Touch-Modus befindet, wird es tatsächlich ausgewählt, wenn es sich im Touch-Modus nur auf dem Bildschirm befindet.
Ein komplizierterer Ansatz:
quelle
Ich fand etwas Interessantes daran.
Ich habe setSelection und scrolltoXY ausprobiert, aber es hat überhaupt nicht funktioniert. Die Liste blieb an derselben Position. Nach einigem Ausprobieren habe ich den folgenden Code erhalten, der funktioniert
Wenn Sie statt Runnable runOnUiThread veröffentlichen, funktioniert dies auch nicht (zumindest auf einigen Geräten).
Dies ist eine sehr seltsame Problemumgehung für etwas, das einfach sein sollte.
quelle
setSelectionFromTop()
funktioniert nicht.VORSICHT!! In AbsListView gibt es einen Fehler, durch den onSaveState () nicht ordnungsgemäß funktioniert, wenn ListView.getFirstVisiblePosition () 0 ist.
Wenn Sie also große Bilder haben, die den größten Teil des Bildschirms einnehmen, und zum zweiten Bild scrollen, aber ein wenig des ersten angezeigt wird, wird die Bildlaufposition nicht gespeichert ...
von AbsListView.java:1650 (Kommentare von mir)
In dieser Situation ist das 'Top' im folgenden Code jedoch eine negative Zahl, was zu anderen Problemen führt, die verhindern, dass der Status korrekt wiederhergestellt wird. Wenn also die Spitze negativ ist, holen Sie sich das nächste Kind
quelle
Das ist genug
quelle
Für einige, die nach einer Lösung für dieses Problem suchen, liegt die Ursache des Problems möglicherweise darin, dass Sie den Adapter für Listenansichten festlegen. Nachdem Sie den Adapter in der Listenansicht eingestellt haben, wird die Bildlaufposition zurückgesetzt. Nur etwas zu beachten. Ich habe den Adapter in mein onCreateView verschoben, nachdem wir den Verweis auf die Listenansicht abgerufen haben, und das Problem wurde für mich gelöst. =)
quelle
Ich poste dies, weil ich überrascht bin, dass niemand dies erwähnt hat.
Nachdem der Benutzer auf die Schaltfläche "Zurück" geklickt hat, kehrt er in demselben Zustand zur Listenansicht zurück, in dem er sie verlassen hat.
Dieser Code überschreibt die Schaltfläche "Auf" und verhält sich genauso wie die Schaltfläche "Zurück". Im Fall von Listenansicht -> Details -> Zurück zur Listenansicht (und ohne weitere Optionen) ist dies der einfachste Code, um die Bildlaufposition und den Inhalt beizubehalten in der Listenansicht.
Achtung: Wenn Sie über die Detailaktivität zu einer anderen Aktivität wechseln können, kehren Sie mit der Aufwärts-Schaltfläche zu dieser Aktivität zurück, sodass Sie den Backbutton-Verlauf bearbeiten müssen, damit dies funktioniert.
quelle
Ist nicht einfach
android:saveEnabled="true"
in der ListView-XML-Deklaration genug?quelle
BESTE LÖSUNG IST:
SIE MÜSSEN NACH DER POST UND IM GEWINDE ANRUFEN!
quelle
Sie können den Bildlaufstatus nach einem Neuladen beibehalten, wenn Sie den Status vor dem Neuladen speichern und danach wiederherstellen. In meinem Fall habe ich eine asynchrone Netzwerkanforderung gestellt und die Liste nach Abschluss in einem Rückruf neu geladen. Hier stelle ich den Zustand wieder her. Codebeispiel ist Kotlin.
quelle
Wenn Sie Fragmente verwenden, die in einer Aktivität gehostet werden, können Sie Folgendes tun:
quelle
Wenn Sie die Bildlaufposition von sich
ListView
selbst speichern / wiederherstellen, duplizieren Sie im Wesentlichen die bereits im Android Framework implementierte Funktionalität. DasListView
stellt die Position des feinen Bildlaufs nur für sich allein wieder her, abgesehen von einer Einschränkung: Wie @aaronvargas erwähnte, gibt es einen FehlerAbsListView
, der es nicht ermöglicht, die Position des feinen Bildlaufs für das erste Listenelement wiederherzustellen. Der beste Weg, um die Bildlaufposition wiederherzustellen, besteht jedoch nicht darin, sie wiederherzustellen. Android Framework wird es besser für Sie tun. Stellen Sie einfach sicher, dass Sie die folgenden Bedingungen erfüllt haben:setSaveEnabled(false)
Methode nicht aufgerufen und keinandroid:saveEnabled="false"
Attribut für die Liste in der XML-Layoutdatei festgelegt habenExpandableListView
Überschreibungsmethodelong getCombinedChildId(long groupId, long childId)
, sodass eine positive lange Zahl zurückgegeben wird (die Standardimplementierung in der KlasseBaseExpandableListAdapter
gibt eine negative Zahl zurück). Hier einige Beispiele:.
ListView
oderExpandableListView
in einem Fragment verwendet wird, erstellen Sie das Fragment bei der Neuerstellung der Aktivität nicht neu (z. B. nach Bildschirmdrehung). Erhalten Sie das Fragment mitfindFragmentByTag(String tag)
Methode.ListView
eine hatandroid:id
und es einzigartig ist.Um die oben genannten Einschränkungen beim ersten Listenelement zu vermeiden, können Sie Ihren Adapter so gestalten, dass er eine spezielle Dummy-Nullpixel-Höhenansicht für die
ListView
Position 0 zurückgibt. In diesem einfachen Beispielprojekt werden die feinen Bildlaufpositionen angezeigtListView
undExpandableListView
wiederhergestellt, während die Bildlaufpositionen nicht explizit gespeichert werden /restauriert. Die Position des feinen Bildlaufs wird auch in komplexen Szenarien mit vorübergehendem Wechsel zu einer anderen Anwendung, doppelter Bildschirmdrehung und Zurückschalten zur Testanwendung perfekt wiederhergestellt. Bitte beachten Sie, dass beim expliziten Beenden der Anwendung (durch Drücken der Zurück-Taste) die Bildlaufposition nicht gespeichert wird (und alle anderen Ansichten ihren Status nicht speichern). https://github.com/voromto/RestoreScrollPosition/releasesquelle
Bei einer von ListActivity abgeleiteten Aktivität, die LoaderManager.LoaderCallbacks mithilfe eines SimpleCursorAdapter implementiert, konnte die Position in onReset () nicht wiederhergestellt werden, da die Aktivität fast immer neu gestartet und der Adapter beim Schließen der Detailansicht neu geladen wurde. Der Trick bestand darin, die Position in onLoadFinished () wiederherzustellen:
in onListItemClick ():
in onLoadFinished ():
in onBackPressed ():
quelle
Keine der hier angebotenen Lösungen schien für mich zu funktionieren. In meinem Fall habe ich ein
ListView
in einem,Fragment
das ich in einem ersetzeFragmentTransaction
, sodassFragment
jedes Mal, wenn das Fragment angezeigt wird, eine neue Instanz erstellt wird, was bedeutet, dass derListView
Status nicht als Mitglied des gespeichert werden kannFragment
.Stattdessen habe ich den Status in meiner benutzerdefinierten
Application
Klasse gespeichert . Der folgende Code soll Ihnen eine Vorstellung davon geben, wie dies funktioniert:Die Grundidee ist, dass Sie den Status außerhalb der Fragmentinstanz speichern. Wenn Ihnen die Idee, ein statisches Feld in Ihrer Anwendungsklasse zu haben, nicht gefällt, können Sie dies wahrscheinlich tun, indem Sie eine Fragmentschnittstelle implementieren und den Status in Ihrer Aktivität speichern.
Eine andere Lösung wäre, es in zu speichern
SharedPreferences
, aber es wird etwas komplizierter, und Sie müssten sicherstellen, dass Sie es beim Start der Anwendung löschen, es sei denn, Sie möchten, dass der Status über App-Starts hinweg beibehalten wird.Um zu vermeiden, dass die Bildlaufposition nicht gespeichert wird, wenn das erste Element sichtbar ist, können Sie ein erstes Dummy-Element mit der
0px
Höhe anzeigen . Dies kann erreicht werden, indem SiegetView()
Ihren Adapter wie folgt überschreiben :quelle
Meine Antwort ist für Firebase und Position 0 ist eine Problemumgehung
und convertView
Position 0 a Fügen Sie ein leeres Element hinzu, das Sie nicht verwenden
Ich habe diese Arbeit vorübergehend gesehen, ohne den Benutzer zu stören. Ich hoffe, sie funktioniert für Sie
quelle
Verwenden Sie diesen folgenden Code:
und wann immer Sie Ihre Daten aktualisieren, verwenden Sie den folgenden Code:
quelle
Ich verwende FirebaseListAdapter und konnte keine der Lösungen zum Laufen bringen. Am Ende habe ich das getan. Ich vermute, es gibt elegantere Wege, aber dies ist eine vollständige und funktionierende Lösung.
Vor onCreate:
Innerhalb des FirebaseListAdapter:
am Start:
onStop:
Da ich dies auch für FirebaseRecyclerAdapter lösen musste, poste ich die Lösung auch hier:
Vor onCreate:
Im FirebaseRecyclerAdapter:
am Start:
onStop:
quelle
Um die ausgezeichnete Antwort von Ryan Newsom zu verdeutlichen und für Fragmente anzupassen und für den üblichen Fall, dass wir von einem "Master" -ListView-Fragment zu einem "Detail" -Fragment und dann zurück zum "Master" navigieren möchten.
Die "Magie" hier ist, dass wenn wir vom Detailfragment zurück zum ListView-Fragment navigieren, die Ansicht nicht neu erstellt wird, wir den ListView-Adapter nicht einstellen, sodass alles so bleibt, wie wir es verlassen haben!
quelle