web-dev-qa-db-fra.com

RecyclerView smoothScroll pour se positionner au centre. Android

J'utilise un gestionnaire de disposition horizontal pour ma RecyclerView. J'ai besoin de faire RecyclerView de la manière suivante: lorsque vous cliquez sur un élément, faites-le smoothScrool à cette position et placez-le au centre de RecyclerView (si possible, par exemple 10 à partir de 20).

Donc, je n’ai aucun problème avec smoothScrollToPosition(), mais comment mettre un objet au centre de RecyclerView ???

Merci!

18
Stan Malcolm

Oui c'est possible.

En implémentant la méthode RecyclerView.SmoothScroller, onTargetFound(View, State, Action).

/**
 * Called when the target position is laid out. This is the last callback SmoothScroller
 * will receive and it should update the provided {@link Action} to define the scroll
 * details towards the target view.
 * @param targetView    The view element which render the target position.
 * @param state         Transient state of RecyclerView
 * @param action        Action instance that you should update to define final scroll action
 *                      towards the targetView
 */
abstract protected void onTargetFound(View targetView, State state, Action action);

Plus précisément dans LinearLayoutManager avec LinearSmoothScroller:

public class CenterLayoutManager extends LinearLayoutManager {

    public CenterLayoutManager(Context context) {
        super(context);
    }

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

    public CenterLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

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

    private static 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);
        }
    }
}
59
user3680200

Améliorations de la réponse - il n'est pas nécessaire de remplacer la LinearLayoutManager

  RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());

  smoothScroller.setTargetPosition(position);

  LinearLayoutManager(LinearLayoutManager for your RecyclerView).startSmoothScroll(smoothScroller);
2
user8944115

Juste au cas où quelqu'un aurait besoin de l'équivalent Kotlin de la classe dans la réponse acceptée.

class CenterLayoutManager : LinearLayoutManager {
    constructor(context: Context) : super(context)
    constructor(context: Context, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)

    override fun smoothScrollToPosition(recyclerView: RecyclerView, state: RecyclerView.State, position: Int) {
        val centerSmoothScroller = CenterSmoothScroller(recyclerView.context)
        centerSmoothScroller.targetPosition = position
        startSmoothScroll(centerSmoothScroller)
    }

    private class CenterSmoothScroller(context: Context) : LinearSmoothScroller(context) {
        override fun calculateDtToFit(viewStart: Int, viewEnd: Int, boxStart: Int, boxEnd: Int, snapPreference: Int): Int = (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2)
    }
}
1
Boda

depuis maintenant (février 2019), je pourrais facilement utiliser ce code dans ListView

(ListView)Word_list_view.smoothScrollToPositionFromTop(your_item_index, center_position.y);

RecyclerView non vérifié, je suppose serait le même.

0
Corxit Sun