RecycleView滑动补充(解决滑动到指定位置顶部的问题)

解决RecycleView滑动到指定位置的问题:


更改前,滑动位置不固定
更改后,滑动位置固定在条目顶部

相信好多人都用过自定义LinearLayoutManager,如下:

import android.content.Context;
import android.graphics.PointF;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;

/**
 * Created by gjl on 2018/3/2.
 */

public class ScrollSpeedLinearLayoutManger extends LinearLayoutManager {
    private float MILLISECONDS_PER_INCH = 0.3f;

    public ScrollSpeedLinearLayoutManger(Context context) {
        super(context);
        //根据不同的屏幕分辨率设置速度
        MILLISECONDS_PER_INCH = context.getResources().getDisplayMetrics().density * 0.1f;
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
        LinearSmoothScroller linearSmoothScroller =
                new LinearSmoothScroller(recyclerView.getContext()) {
                    @Override
                    public PointF computeScrollVectorForPosition(int targetPosition) {
                        return ScrollSpeedLinearLayoutManger.this
                                .computeScrollVectorForPosition(targetPosition);
                    }

                    //This returns the milliseconds it takes to
                    //scroll one pixel.
                    @Override
                    protected float calculateSpeedPerPixel
                    (DisplayMetrics displayMetrics) {
                        //返回滑动一个pixel需要多少毫秒
                        return MILLISECONDS_PER_INCH / displayMetrics.density;                      
                    }
                };
        linearSmoothScroller.setTargetPosition(position);
        startSmoothScroll(linearSmoothScroller);
    }
}

使用时:

ScrollSpeedLinearLayoutManger  linearLayoutManger  = new ScrollSpeedLinearLayoutManger(MainActivity.this);
recycleView.setLayoutManager(linearLayoutManger);
//滑动方法
linearLayoutManger.smoothScrollToPosition(recycleView,null,position);

结果发现滑动方法不好用了,使用smoothScrollToPosition时,移动到前面的项时,它默认会将要显示的项底部,但是移动到后面的项时,它默认会将要显示的项顶部,当前移动项在屏幕上显示时,不会移动,用过的应该都有所了解。

解决问题

从上面的代码看到,我们只是设置了LinearSmoothScroller,那么查看一下LinearSmoothScroller的源码发现:

 /**
     * Align child view's left or top with parent view's left or top
     *
     * @see #calculateDtToFit(int, int, int, int, int)
     * @see #calculateDxToMakeVisible(android.view.View, int)
     * @see #calculateDyToMakeVisible(android.view.View, int)
     */
    public static final int SNAP_TO_START = -1;

    /**
     * Align child view's right or bottom with parent view's right or bottom
     *
     * @see #calculateDtToFit(int, int, int, int, int)
     * @see #calculateDxToMakeVisible(android.view.View, int)
     * @see #calculateDyToMakeVisible(android.view.View, int)
     */
    public static final int SNAP_TO_END = 1;

    /**
     * 

Decides if the child should be snapped from start or end, depending on where it * currently is in relation to its parent.

*

For instance, if the view is virtually on the left of RecyclerView, using * {@code SNAP_TO_ANY} is the same as using {@code SNAP_TO_START}

* * @see #calculateDtToFit(int, int, int, int, int) * @see #calculateDxToMakeVisible(android.view.View, int) * @see #calculateDyToMakeVisible(android.view.View, int) */ public static final int SNAP_TO_ANY = 0; /** * When scrolling towards a child view, this method defines whether we should align the top * or the bottom edge of the child with the parent RecyclerView. * * @return SNAP_TO_START, SNAP_TO_END or SNAP_TO_ANY; depending on the current target vector * @see #SNAP_TO_START * @see #SNAP_TO_END * @see #SNAP_TO_ANY */ protected int getVerticalSnapPreference() { return mTargetVector == null || mTargetVector.y == 0 ? SNAP_TO_ANY : mTargetVector.y > 0 ? SNAP_TO_END : SNAP_TO_START; }

LinearSmoothScroller里面3个状态,这里我们只需要在设置LinearSmoothScroller的时候重写 getVerticalSnapPreference()方法,让滑动位置始终滑动到条目开始位置就好了.

/**
 * Created by gjl on 2018/3/2.
 */

public class ScrollSpeedLinearLayoutManger extends LinearLayoutManager {
    private float MILLISECONDS_PER_INCH = 0.3f;

    public ScrollSpeedLinearLayoutManger(Context context) {
        super(context);
        MILLISECONDS_PER_INCH = context.getResources().getDisplayMetrics().density * 0.1f;
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
        LinearSmoothScroller linearSmoothScroller =
                new LinearSmoothScroller(recyclerView.getContext()) {
                    @Override
                    public PointF computeScrollVectorForPosition(int targetPosition) {
                        return ScrollSpeedLinearLayoutManger.this
                                .computeScrollVectorForPosition(targetPosition);
                    }

                    //This returns the milliseconds it takes to
                    //scroll one pixel.
                    @Override
                    protected float calculateSpeedPerPixel
                    (DisplayMetrics displayMetrics) {
                        return MILLISECONDS_PER_INCH / displayMetrics.density;
                        //返回滑动一个pixel需要多少毫秒
                    }
                    
                    //重写这个方法,保证滑动到指定条目的顶部
                    @Override
                    protected int getVerticalSnapPreference() {
                        return SNAP_TO_START;
                    }

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

}

你可能感兴趣的:(RecycleView滑动补充(解决滑动到指定位置顶部的问题))