web-dev-qa-db-fra.com

Android: Contrôlez le défilement en douceur sur la vue du recycleur

J'utilise Recyclerview avec CardView. Je sais comment contrôler la vitesse en mode liste. Mais pas pour Recyclerview.

J'ai cherché beaucoup dans le nom de la classe trouvée SmoothScroll . Comment l'utiliser? Je n'ai aucune idée! En ce moment, Recyclerview par défaut est rapide.

UPDATE:

J'ai résumé Gil Répondre avec this

49
Shabbir Dhangot

Vous ne comprenez pas ce que vous voulez dire lorsque vous dites "smoothScroll". Vous pourriez faire référence à la fonction automatique "smoothScrollToPosition" qui défilera automatiquement à une position spécifiée, vous pourriez parler de défilement manuel et vous pourriez parler de flinging. Par souci de prospérité, je vais tenter de répondre à toutes ces questions maintenant.

1. Défilement automatique en douceur.

Dans votre gestionnaire de disposition, vous devez implémenter la méthode smoothScrollToPosition:

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, State state, int position)
    {
        // A good idea would be to create this instance in some initialization method, and just set the target position in this method.
        LinearSmoothScroller smoothScroller = new LinearSmoothScroller(getContext())
        {
            @Override
            public PointF computeScrollVectorForPosition(int targetPosition)
            {
                int yDelta = calculateCurrentDistanceToPosition(targetPosition);
                return new PointF(0, yDelta);
            }

            // This is the important method. This code will return the amount of time it takes to scroll 1 pixel.
            // This code will request X milliseconds for every Y DP units.
            @Override
            protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics)
            {
                return X / TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, Y, displayMetrics);
            }

        };
        smoothScroller.setTargetPosition(position);

        startSmoothScroll(smoothScroller);
    }

Dans cet exemple, j'utilise une méthode d'assistance nommée "CalculateCurrentDistanceToPosition". Cela peut être un peu délicat, car cela implique de garder une trace de votre position de défilement actuelle et de calculer la position de défilement d'une position y donnée. Vous pouvez trouver un exemple sur la façon de suivre le parchemin du recycleur y ici .

Le calcul du défilement y d'une position donnée dépend vraiment de ce que votre recycleur affiche. En supposant que tous vos articles aient la même hauteur, vous pouvez le calculer en effectuant le calcul suivant:

targetScrollY = targetPosition * itemHeight

Ensuite, pour calculer la distance à parcourir, il suffit de soustraire le défilement actuel y avec le défilement cible y:

private int calculateCurrentDistanceToPosition(int targetPosition) {
    int targetScrollY = targetPosition * itemHeight;
    return targetScrollY - currentScrollY;
}

2. Ralentir le défilement manuel.

Encore une fois, vous devez éditer votre gestionnaire de disposition, cette fois-ci - la méthode scrollVerticallyBy:

    @Override
    public int scrollVerticallyBy(int delta, Recycler recycler, State state)
    {
       // write your limiting logic here to prevent the delta from exceeding the limits of your list.

       int prevDelta = delta;
       if (getScrollState() == SCROLL_STATE_DRAGGING)
            delta = (int)(delta > 0 ? Math.max(delta * MANUAL_SCROLL_SLOW_RATIO, 1) : Math.min(delta * MANUAL_SCROLL_SLOW_RATIO, -1));  

       // MANUAL_SCROLL_SLOW_RATIO is between 0 (no manual scrolling) to 1 (normal speed) or more (faster speed).
       // write your scrolling logic code here whereby you move each view by the given delta

        if (getScrollState() == SCROLL_STATE_DRAGGING)
            delta = prevDelta;

        return delta;
    }

Edit: Dans la méthode ci-dessus, j'appelle "getScrollState()". C'est une méthode de RecyclerView. Dans cette implémentation, ma coutume LayoutManager est une classe imbriquée de ma coutume RecyclerView. Si cela ne fonctionne pas pour vous, vous pouvez essayer de saisir l'état de défilement via un modèle d'interface.

3. Ralentissez la vitesse de projection

Ici, vous voulez réduire la vitesse de défilement. Vous devrez remplacer la méthode fling dans votre sous-classe RecyclerView:

@Override
public boolean fling(int velocityX, int velocityY)
{
     velocityY *= FLING_SCALE_DOWN_FACTOR; // (between 0 for no fling, and 1 for normal fling, or more for faster fling).

     return super.fling(velocityX, velocityY);
}

Il m'est difficile de fournir une solution plus personnalisée, car vous n'avez posté aucun de vos codes, ni fourni beaucoup d'informations sur votre configuration, mais j'espère que cela couvre la plupart des bases et vous aidera à trouver la meilleure solution pour vous.

100
Gil Moshayof

Je viens de simplifier la réponse comment l'utiliser pour contrôler le défilement lisse.

Créer une classe

import Android.content.Context;
import Android.support.v7.widget.RecyclerView;
import Android.util.AttributeSet;

public class CustomRecyclerView extends RecyclerView {

    Context context;

    public CustomRecyclerView(Context context) {
        super(context);
        this.context = context;
    }

    public CustomRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean fling(int velocityX, int velocityY) {

        velocityY *= 0.7;
        // velocityX *= 0.7; for Horizontal recycler view. comment velocityY line not require for Horizontal Mode.

        return super.fling(velocityX, velocityY);
    }

}

Ajustez la vitesse en remplaçant ,7 à votre valeur.

Maintenant, utilisez cette classe dans votre XML comme ceci.

<<yourpackage>.CustomRecyclerView
    Android:id="@+id/my_recycler_view"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:scrollbars="vertical" />

Lisez RecyclerView dans Java comme.

CustomRecyclerView mRecyclerView;
mRecyclerView = (CustomRecyclerView) findViewById(R.id.my_recycler_view);
32
Shabbir Dhangot

Implémentez simplement smoothScrollToPosition () de votre LinearLayoutManager:

LinearLayoutManager layoutManager = new LinearLayoutManager(this) {

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
        LinearSmoothScroller smoothScroller = new LinearSmoothScroller(this) {

            private static final float SPEED = 300f;// Change this value (default=25f)

            @Override
            protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                return SPEED / displayMetrics.densityDpi;
            }

        };
        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
    }

};
27
Blunderer