Mantener/Guardar/Restaurar la posición de desplazamiento al regresar a ListView

Resuelto rantravee asked hace 54 años • 20 respuestas

Tengo un largo ListViewpor el que el usuario puede desplazarse antes de volver a la pantalla anterior. Cuando el usuario ListViewvuelva a abrir esto, quiero que la lista se desplace al mismo punto que estaba anteriormente. ¿Alguna idea sobre cómo lograr esto?

rantravee avatar Jan 01 '70 08:01 rantravee
Aceptado

Prueba esto:

// 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);

Explicación:

ListView.getFirstVisiblePosition()devuelve el elemento de lista más visible. Pero este elemento puede estar parcialmente desplazado fuera de la vista, y si desea restaurar la posición de desplazamiento exacta de la lista, necesita obtener este desplazamiento. Entonces ListView.getChildAt(0)devuelve el Viewelemento de la lista superior y luego View.getTop() - mList.getPaddingTop()devuelve su desplazamiento relativo desde la parte superior del archivo ListView. Luego, para restaurar la ListViewposición de desplazamiento de , llamamos ListView.setSelectionFromTop()con el índice del elemento que queremos y un desplazamiento para posicionar su borde superior desde la parte superior del ListView.

ian avatar Jun 14 '2010 07:06 ian
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);
    }
}
Eugene Mymrin avatar Apr 16 '2011 18:04 Eugene Mymrin

Adopté la solución sugerida por @(Kirk Woll) y me funciona. También he visto en el código fuente de Android para la aplicación "Contactos" que utilizan una técnica similar. Me gustaría agregar algunos detalles más: En la parte superior de mi clase derivada de ListActivity:

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

Luego, algún método anula:

@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);
}

Por supuesto, "loadData" es mi función para recuperar datos de la base de datos y ponerlos en la lista.

En mi dispositivo Froyo, esto funciona tanto cuando cambias la orientación del teléfono como cuando editas un elemento y vuelves a la lista.

Giorgio Barchiesi avatar Apr 17 '2011 15:04 Giorgio Barchiesi