android simple Comment enregistrer la position de défilement de RecyclerView à l'aide de RecyclerView.State?



recyclerview getscrollstate (8)

le magasin

lastFirstVisiblePosition = ((LinearLayoutManager)rv.getLayoutManager()).findFirstCompletelyVisibleItemPosition();

Restaurer

((LinearLayoutManager) rv.getLayoutManager()).scrollToPosition(lastFirstVisiblePosition);

et si cela ne fonctionne pas, essayez

((LinearLayoutManager) rv.getLayoutManager()).scrollToPositionWithOffset(lastFirstVisiblePosition,0)

Mettez store dans onPause() et restaurez dans onResume()

J'ai une question à propos de RecyclerView.State d'Android.

J'utilise un RecyclerView, comment pourrais-je l'utiliser et le lier avec RecyclerView.State?

Mon but est de sauvegarder la position de défilement de RecyclerView .


Answer #1

I Définissez les variables dans onCreate (), enregistrez la position de défilement dans onPause () et définissez la position de défilement dans onResume ()

public static int index = -1;
public static int top = -1;
LinearLayoutManager mLayoutManager;

@Override
public void onCreate(Bundle savedInstanceState)
{
    //Set Variables
    super.onCreate(savedInstanceState);
    cRecyclerView = ( RecyclerView )findViewById(R.id.conv_recycler);
    mLayoutManager = new LinearLayoutManager(this);
    cRecyclerView.setHasFixedSize(true);
    cRecyclerView.setLayoutManager(mLayoutManager);

}

@Override
public void onPause()
{
    super.onPause();
    //read current recyclerview position
    index = mLayoutManager.findFirstVisibleItemPosition();
    View v = cRecyclerView.getChildAt(0);
    top = (v == null) ? 0 : (v.getTop() - cRecyclerView.getPaddingTop());
}

@Override
public void onResume()
{
    super.onResume();
    //set recyclerview position
    if(index != -1)
    {
        mLayoutManager.scrollToPositionWithOffset( index, top);
    }
}

Answer #2

C'est ainsi que je restaure la position RecyclerView avec GridLayoutManager après la rotation lorsque vous avez besoin de recharger des données depuis Internet avec AsyncTaskLoader.

Créez une variable globale de Parcelable et GridLayoutManager et une chaîne finale statique:

private Parcelable savedRecyclerLayoutState;
private GridLayoutManager mGridLayoutManager;
private static final String BUNDLE_RECYCLER_LAYOUT = "recycler_layout";

Enregistrer l'état de gridLayoutManager dans onSaveInstance ()

 @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putParcelable(BUNDLE_RECYCLER_LAYOUT, 
            mGridLayoutManager.onSaveInstanceState());
        }

Restaurer dans onRestoreInstanceState

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        //restore recycler view at same position
        if (savedInstanceState != null) {
            savedRecyclerLayoutState = savedInstanceState.getParcelable(BUNDLE_RECYCLER_LAYOUT);
        }
    }

Puis, lorsque le chargeur récupère les données d'Internet, vous rétablissez la position de recyclage dans onLoadFinished ()

if(savedRecyclerLayoutState!=null){
                mGridLayoutManager.onRestoreInstanceState(savedRecyclerLayoutState);
            }

... bien sûr, vous devez instancier gridLayoutManager dans onCreate. À votre santé


Answer #3

Si vous utilisez LinearLayoutManager, il est livré avec l'API de sauvegarde linearLayoutManagerInstance.onSaveInstanceState() et la restauration de l'api linearLayoutManagerInstance.onRestoreInstanceState(...)

Avec cela, vous pouvez enregistrer la parcelable retournée à votre outState. par exemple,

outState.putParcelable("KeyForLayoutManagerState", linearLayoutManagerInstance.onSaveInstanceState());

et restaurez la position de restauration avec l'état que vous avez enregistré. par exemple,

Parcelable state = savedInstanceState.getParcelable("KeyForLayoutManagerState");
linearLayoutManagerInstance.onRestoreInstanceState(state);

Pour tout terminer, votre code final ressemblera à quelque chose comme

private static final String BUNDLE_RECYCLER_LAYOUT = "classname.recycler.layout";

/**
 * This is a method for Fragment. 
 * You can do the same in onCreate or onRestoreInstanceState
 */
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
    super.onViewStateRestored(savedInstanceState);

    if(savedInstanceState != null)
    {
        Parcelable savedRecyclerLayoutState = savedInstanceState.getParcelable(BUNDLE_RECYCLER_LAYOUT);
        recyclerView.getLayoutManager().onRestoreInstanceState(savedRecyclerLayoutState);
    }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putParcelable(BUNDLE_RECYCLER_LAYOUT, recyclerView.getLayoutManager().onSaveInstanceState());
}

Edit: Vous pouvez également utiliser les mêmes API avec GridLayoutManager, car il s'agit d'une sous-classe de LinearLayoutManager. Merci @wegsehen pour la suggestion.

Edit: Souvenez-vous que si vous chargez également des données dans un thread d'arrière-plan, vous devrez appeler onRestoreInstanceState dans votre méthode onPostExecute / onLoadFinished pour que la position soit restaurée lors du changement d'orientation, par ex.

@Override
protected void onPostExecute(ArrayList<Movie> movies) {
    mLoadingIndicator.setVisibility(View.INVISIBLE);
    if (movies != null) {
        showMoviePosterDataView();
        mDataAdapter.setMovies(movies);
      mRecyclerView.getLayoutManager().onRestoreInstanceState(mSavedRecyclerLayoutState);
        } else {
            showErrorMessage();
        }
    }

Answer #4

Comment envisagez-vous de sauvegarder la dernière position enregistrée avec RecyclerView.State ?

Vous pouvez toujours compter sur un bon état de sauvegarde. Étendez RecyclerView et remplacez onSaveInstanceState () et onRestoreInstanceState() :

@Override
    protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        LayoutManager layoutManager = getLayoutManager();
        if(layoutManager != null && layoutManager instanceof LinearLayoutManager){
            mScrollPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
        }
        SavedState newState = new SavedState(superState);
        newState.mScrollPosition = mScrollPosition;
        return newState;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        super.onRestoreInstanceState(state);
        if(state != null && state instanceof SavedState){
            mScrollPosition = ((SavedState) state).mScrollPosition;
            LayoutManager layoutManager = getLayoutManager();
            if(layoutManager != null){
              int count = layoutManager.getChildCount();
              if(mScrollPosition != RecyclerView.NO_POSITION && mScrollPosition < count){
                  layoutManager.scrollToPosition(mScrollPosition);
              }
            }
        }
    }

    static class SavedState extends android.view.View.BaseSavedState {
        public int mScrollPosition;
        SavedState(Parcel in) {
            super(in);
            mScrollPosition = in.readInt();
        }
        SavedState(Parcelable superState) {
            super(superState);
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeInt(mScrollPosition);
        }
        public static final Parcelable.Creator<SavedState> CREATOR
                = new Parcelable.Creator<SavedState>() {
            @Override
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            @Override
            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }

Answer #5

Vous n'avez plus besoin de sauvegarder et restaurer l'état par vous-même. Si vous définissez un ID unique dans xml et recyclerView.setSaveEnabled (true) (true par défaut), le système le fera automatiquement. Voici plus à ce sujet: http://trickyandroid.com/saving-android-view-state-correctly/


Answer #6

Je voulais sauvegarder la position de défilement de Recycler View lorsque je naviguais loin de mon activité de liste, puis cliquer sur le bouton de retour pour revenir en arrière. La plupart des solutions fournies pour ce problème étaient soit beaucoup plus compliquées que nécessaire ou ne fonctionnaient pas pour ma configuration, alors j'ai pensé partager ma solution.

D'abord enregistrer votre état d'instance dans onPause comme beaucoup l'ont montré. Je pense qu'il vaut la peine de souligner ici que cette version de onSaveInstanceState est une méthode de la classe RecyclerView.LayoutManager.

private LinearLayoutManager mLayoutManager;
Parcelable state;

        @Override
        public void onPause() {
            super.onPause();
            state = mLayoutManager.onSaveInstanceState();
        }

La clé pour que cela fonctionne correctement est de vous assurer que vous appelez onRestoreInstanceState après avoir attaché votre adaptateur, comme certains l'ont indiqué dans d'autres threads. Cependant, l'appel de méthode réel est beaucoup plus simple que beaucoup l'ont indiqué.

private void someMethod() {
    mVenueRecyclerView.setAdapter(mVenueAdapter);
    mLayoutManager.onRestoreInstanceState(state);
}

Answer #7

Activity.java:

public RecyclerView.LayoutManager mLayoutManager;

Parcelable state;

    mLayoutManager = new LinearLayoutManager(this);


// Inside `onCreate()` lifecycle method, put the below code :

    if(state != null) {
    mLayoutManager.onRestoreInstanceState(state);

    } 

    @Override
    protected void onResume() {
        super.onResume();

        if (state != null) {
            mLayoutManager.onRestoreInstanceState(state);
        }
    }   

   @Override
    protected void onPause() {
        super.onPause();

        state = mLayoutManager.onSaveInstanceState();

    }   

Pourquoi j'utilise OnSaveInstanceState() dans onPause() signifie, Alors que le passage à une autre activité onPause serait appelé.Il va enregistrer cette position de défilement et restaurer la position lorsque nous revenons d'une autre activité.





android-recyclerview