414 Stimmen

Beibehalten/Speichern/Wiederherstellen der Bildlaufposition bei der Rückkehr zu einer ListView

Ich habe eine lange ListView dass der Benutzer einen Bildlauf durchführen kann, bevor er zum vorherigen Bildschirm zurückkehrt. Wenn der Benutzer diese Seite öffnet ListView Ich möchte, dass die Liste wieder an die gleiche Stelle wie zuvor gescrollt wird. Irgendwelche Ideen, wie man das erreichen kann?

643voto

ian Punkte 15537

Versuchen Sie dies:

// save index and top position
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - mList.getPaddingTop());

// ...

// restore index and position
mList.setSelectionFromTop(index, top);

Erläuterung:

ListView.getFirstVisiblePosition() gibt das oberste sichtbare Listenelement zurück. Dieses Element kann jedoch teilweise aus dem Sichtfeld gerollt sein, und wenn Sie die genaue Rollposition der Liste wiederherstellen wollen, müssen Sie diesen Versatz ermitteln. Also ListView.getChildAt(0) gibt die View für das oberste Listenelement und dann View.getTop() - mList.getPaddingTop() gibt seinen relativen Versatz vom oberen Rand der Datei ListView . Dann, zur Wiederherstellung der ListView die Scroll-Position, rufen wir ListView.setSelectionFromTop() mit dem Index des gewünschten Elements und einem Versatz, um dessen Oberkante vom oberen Rand des ListView .

553voto

Eugene Mymrin Punkte 5636
Parcelable state;

@Override
public void onPause() {    
    // Save ListView state @ onPause
    Log.d(TAG, "saving listview state");
    state = listView.onSaveInstanceState();
    super.onPause();
}
...

@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    // Set new items
    listView.setAdapter(adapter);
    ...
    // Restore previous state (including selected item index and scroll position)
    if(state != null) {
        Log.d(TAG, "trying to restore listview state");
        listView.onRestoreInstanceState(state);
    }
}

54voto

Giorgio Barchiesi Punkte 5942

Ich habe die von @(Kirk Woll) vorgeschlagene Lösung übernommen, und sie funktioniert bei mir. Ich habe auch im Android-Quellcode für die App "Kontakte" gesehen, dass dort eine ähnliche Technik verwendet wird. Ich möchte noch einige Details hinzufügen: Oben auf meiner ListActivity-abgeleiteten Klasse:

private static final String LIST_STATE = "listState";
private Parcelable mListState = null;

Dann werden einige Methoden außer Kraft gesetzt:

@Override
protected void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);
    mListState = state.getParcelable(LIST_STATE);
}

@Override
protected void onResume() {
    super.onResume();
    loadData();
    if (mListState != null)
        getListView().onRestoreInstanceState(mListState);
    mListState = null;
}

@Override
protected void onSaveInstanceState(Bundle state) {
    super.onSaveInstanceState(state);
    mListState = getListView().onSaveInstanceState();
    state.putParcelable(LIST_STATE, mListState);
}

Natürlich ist "loadData" meine Funktion, um Daten aus der DB abzurufen und sie in die Liste zu stellen.

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.

26voto

Francesco Laurita Punkte 23236

Ein sehr einfacher Weg:

/** Save the position **/
int currentPosition = listView.getFirstVisiblePosition();

//Here u should save the currentPosition anywhere

/** Restore the previus saved position **/
listView.setSelection(savedPosition);

Die Methode setSelection setzt die Liste auf das angegebene Element zurück. Wenn Sie sich nicht im Berührungsmodus befinden, wird das Element tatsächlich ausgewählt, wenn Sie sich im Berührungsmodus befinden, wird das Element nur auf dem Bildschirm positioniert.

Ein etwas komplizierterer Ansatz:

listView.setOnScrollListener(this);

//Implements the interface:
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
    mCurrentX = view.getScrollX();
    mCurrentY = view.getScrollY();
}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {

}

//Save anywere the x and the y

/** Restore: **/
listView.scrollTo(savedX, savedY);

17voto

shalafi Punkte 3893

Ich habe dazu etwas Interessantes gefunden.

Ich habe versucht, setSelection und scrolltoXY, aber es hat überhaupt nicht funktionieren, die Liste blieb in der gleichen Position, nach einigen Versuch und Irrtum habe ich den folgenden Code, der funktioniert

final ListView list = (ListView) findViewById(R.id.list);
list.post(new Runnable() {            
    @Override
    public void run() {
        list.setSelection(0);
    }
});

Wenn Sie statt der Runnable zu posten runOnUiThread versuchen, funktioniert es auch nicht (zumindest auf einigen Geräten)

Dies ist eine sehr seltsame Lösung für etwas, das eigentlich ganz einfach sein sollte.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X