web-dev-qa-db-fra.com

Comment enregistrer la position de défilement de RecyclerView dans Android?

J'ai la vue Recycler qui se trouve à l'intérieur de SwipeRefreshLayout. De plus, vous avez la possibilité d'ouvrir chaque élément d'une autre activité . Après être revenu à Recycler, vous devez faire défiler jusqu'à l'élément choisi ou au précédent Y . Comment procéder?

Oui, j'ai cherché sur Google des articles trouvés dans StackOverFlow sur la sauvegarde d'un exemple de gestionnaire de présentation, comme celui-ci: RecyclerView enregistrer/restaurer l'état entre les activités .

METTRE À JOUR

Actuellement, j'ai ce genre de problème de résolution, mais, bien sûr, cela ne fonctionne pas non plus.

private int scrollPosition;

...//onViewCreated - it is fragment
recyclerView.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(llm);
data = new ArrayList<>();
adapter.setData(getActivity(), data);
recyclerView.setAdapter(adapter);
...

@Override
public void onResume() {
    super.onResume();
    recyclerView.setScrollY(scrollPosition);
}

@Override
public void onPause() {
    super.onPause();
    scrollPosition = recyclerView.getScrollY();
}

Oui, j'ai essayé scrollTo (int, int) - ne fonctionne pas.

Maintenant, j'ai essayé de faire défiler, par exemple, jusqu'à Y = 100, mais cela ne défilait pas du tout.

16
DefaultXYZ

Enregistrer l'état actuel de la position de la vue de recyclage @onPause:

    positionIndex= llManager.findFirstVisibleItemPosition();
    View startView = rv.getChildAt(0);
    topView = (startView == null) ? 0 : (startView.getTop() - rv.getPaddingTop());

Restaurez la position de défilement @onResume:

    if (positionIndex!= -1) {
        llManager.scrollToPositionWithOffset(positionIndex, topView);
    }

ou une autre manière peut être @onPause: 

long currentVisiblePosition = 0;
currentVisiblePosition = ((LinearLayoutManager)rv.getLayoutManager()).findFirstCompletelyVisibleItemPosition();

restaurer @onResume:

((LinearLayoutManager) rv.getLayoutManager()).scrollToPosition(currentVisiblePosition);
currentVisiblePosition = 0;
33
Madhukar Hebbar

Beaucoup de ces réponses semblent compliquer les choses.

LayoutManager prend en charge onRestoreInstanceState prêt à l'emploi, il n'est donc pas nécessaire de sauvegarder les positions de défilement, etc. La méthode intégrée enregistre déjà les positions parfaites en pixels.

exemple de code de fragment (vérification de null, etc. supprimée pour plus de clarté):

private Parcelable listState;
private RecyclerView list;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    listState=savedInstanceState.getParcelable("ListState");

}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.putParcelable("ListState", list.getLayoutManager().onSaveInstanceState());

}

alors il suffit d'appeler

list.getLayoutManager().onRestoreInstanceState(listState);

une fois que vos données ont été rattachées à votre RecyclerView

18
Kuffs

Utilisez votre vue recycleur linearlayoutmanager pour obtenir la position de défilement

int position = 0;
if (linearLayoutManager != null) {
   scrollPosition = inearLayoutManager.findFirstVisibleItemPosition();
}

et lors de la restauration, utilisez le code suivant

if (linearLayoutManager != null) {
  cardRecyclerView.scrollToPosition(mScrollPosition);
}

J'espère que cela vous aide

2
Nikhil

pour enregistrer la position dans les préférences, ajoutez ceci à votre onStop ()

 int currentVisiblePosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
 getPreferences(MODE_PRIVATE).edit().putInt("listPosition", currentVisiblePosition).apply();

puis rétablir la position comme ça 

 if (getItemCount() == 0) {
     int savedListPosition = getPreferences(MODE_PRIVATE).getInt("listPosition", 0);
     recyclerView.getLayoutManager().scrollToPosition(savedListPosition); }

ce dernier code doit être ajouté dans un événement de l'adaptateur (pas sûr, mais dans mon cas onEvent () - com.google.firebase.firestore.EventListener)

0
Dan Alboteanu

Pour une raison quelconque, il existe de nombreux conseils/suggestions très trompeurs sur la façon de sauvegarder et de restaurer la position de défilement dans votre_scrolling_container lors de changements d’orientation.

Prendre la position de défilement actuelle et la sauvegarder dans onSaveInstanceState de l’activité Étendre une certaine vue défilable pour qu’il en soit de même là Empêcher la destruction de l’activité par rotation .__

Mais en réalité, tout est beaucoup plus simple, car Android le fait déjà pour vous!

Si vous examinez de plus près les sources RecyclerView/ListView/ScrollView/NestedScrollView, vous verrez que chacune d’elles enregistre sa position de défilement dans onSaveInstanceState. Et lors du premier passage de présentation, ils essaient de faire défiler jusqu'à cette position dans la méthode onLayout.

Il ne vous reste que 2 choses à faire pour que tout fonctionne correctement:

  1. Définissez un identifiant pour votre vue défilable, ce qui est probablement déjà fait. Sinon, Android ne pourra pas enregistrer automatiquement l'état d'affichage.

  2. Fournissez des données avant la première passe de présentation pour que les limites de défilement soient identiques à celles que vous aviez avant la rotation. C’est là que les développeurs ont généralement des problèmes.

0
Andrey T