web-dev-qa-db-fra.com

Comment faire pour que RecyclerView défile en douceur?

Cela ressemble plus à une question générique, mais après beaucoup de recherches et d’essais, je ne suis pas en mesure de comprendre pourquoi c’est si difficile à réaliser. Ceci est la réponse la plus proche que je puisse trouver mais que je ne puisse toujours pas mettre en œuvre.

Pour être précis, j'utilise RecyclerView avec GridLayoutManager. Tout ce que je veux, c'est que la disposition de la grille défile sans à-coups (comme l'application gallary par défaut). Rien d'extraordinaire, mais l'implémentation par défaut du gestionnaire de disposition de la grille défile la vue de manière saccadée. J'ai essayé d'implémenter la méthode du lien ci-dessus mais sans succès.

J'ai également essayé d'implémenter LinearSmoothScroller mais je ne sais pas comment implémenter la méthode computeScrollVectorForPosition. La documentation de Google sur computeScrollVectorForPosition a littéralement 0 mots. 

J'ai trouvé ce tutoriel en 3 parties , mais il m'a été d'une aide minime. Donc, tout ce que je veux demander est: peut-il y avoir une sorte de code de gabarit que nous pouvons implémenter dans LinearSmoothScroller ou en étendant RecyclerView.SmoothScroller et obtenir un défilement régulier? Même si le code dépend du nombre d'éléments et d'éléments par ligne dans Gridlayout, il doit exister une méthode pour le faire facilement. Est-ce que j'ai râté quelque chose ?

13
rockfight

La source typique du défilement "saccadé" dans Android est l'application qui prend trop de temps sur le fil principal de l'application mettant à jour l'interface utilisateur. Dans le cas de RecyclerView, cela signifierait prendre trop de temps dans onBindViewHolder() ou éventuellement dans onCreateViewHolder(). Chacune d'entre elles doit être renvoyée moins d'une milliseconde, ce qui signifie que vous ne pouvez pas effectuer d'E/S disque ni d'E/S réseau en elles. 

pense que j'ai trouvé le problème. J'utilise holder.photo.setImageBitmap (BitmapFactory.decodeFile (itemList.get (position) .get AbsolutePath ())); sur onBindViewHolder () et le fichier image pèse environ 100 Ko, avec environ une douzaine d’images dans la liste.

Oui, ce sera le disque I/O et le décodage d’image sur le thread principal de l’application. Ce sera assez lent pour provoquer un jank dans l'interface utilisateur (c'est-à-dire, le défilement "saccadé").

Pensez à utiliser une bibliothèque de chargement d'images, telle que Picasso ou Universal Image Loader, car elles peuvent renseigner votre ImageView à partir du bitmap de manière asynchrone.

Cet exemple d'application utilise Universal Image Loader pour aider à renseigner le contenu d'une RecyclerView (avec GridLayoutManager), la source de données correspondant aux vidéos disponibles sur le périphérique.

31
CommonsWare

Ajoutez ceci partout où vous avez déclaré RecyclerView dans votre Activity ou Fragment

RecyclerView mRecyclerview = (RecyclerView) findViewById(...);
mRecyclerview.setNestedScrollingEnabled(false);

setNestedScrollview(false) fait le travail pour vous.

28
Ahmed Raza

Je viens juste de faire face à ce problème et la désactivation du défilement imbriqué a corrigé le problème.

yourRecyclerview.setNestedScrollingEnabled(false);

Ou vous pouvez modifier la valeur du fichier xml où vous avez défini RecyclerView:

<Android.support.v7.widget.RecyclerView
    Android:id="@+id/yourRecyclerView"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:nestedScrollingEnabled="false"/>
11
Arman Ramezanzadeh

Je viens juste de faire face à ce problème, et j’ai eu J’ai mis la RecyclerView dans ScrollView Donc, s'il vous plaît, ne mettez jamais la RecyclerView dans la ScrollView qui peut aussi causer.

mLayoutManager.findFirstVisibleItemPosition()

Cela retourne toujours une valeur fixe. Et aussi vérifier 

recyclerview.setNestedScrollingEnabled(false);
2
Shyam Sundar
Android:animateLayoutChanges="false"
1
Bishwajeet Biswas

J'ai rendu le défilement régulier en surchargeant la méthode calculateSpeedPerPixel(DisplayMetrics displayMetrics):

public class CustomLayoutManager extends LinearLayoutManager {

    protected CenterLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
        RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());
        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
    }

    private class CenterSmoothScroller extends LinearSmoothScroller {

        CenterSmoothScroller(Context context) {
            super(context);
        }

        @Override
        public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
            return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
        }

        @Override
        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
            return 0.5f; //pass as per your requirement
        }
    }
}
0
SKP