RecyclerView自动滚动

smoothScrollToPosition()
在使用RecyclerView的时候,有一些场景需要RecyclerView能自动滑动到指定的item,这种情况可以调用RecyclerView的以下方法来实现:

scrollToPosition(int position)

smoothScrollToPosition(int position)
这两个方法传入需要滑动到的item的position就可以实现跳转到相应的item,区别是scrollToPosition()会立即跳转到相应item,不会有滑动的效果,smoothScrollToPosition()跳转的同时,会有滑动的效果,但是滑动速度很快,用户体验效果不好,如何能控制速度达到一个好的效果呢?

先来看下smoothScrollToPosition()的源码:

    public void smoothScrollToPosition(int position) {
        if (mLayoutFrozen) {
            return;
        }
        if (mLayout == null) {
            Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. " +
                    "Call setLayoutManager with a non-null argument.");
            return;
        }
        mLayout.smoothScrollToPosition(this, mState, position);
    }
它最终是调用了mLayout.smoothScrollToPosition(this, mState, position),mLayout是RecyclerView的布局管理器,比如线性布局管理器LinearLayoutManager:

mRecyclerView.setLayoutManager(mLinearLayoutManager); 

来看下smoothScrollToPosition()在线性布局管理器中的实现:

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
            int position) {
        LinearSmoothScroller linearSmoothScroller =
                new LinearSmoothScroller(recyclerView.getContext());
        linearSmoothScroller.setTargetPosition(position);
        startSmoothScroll(linearSmoothScroller);
    }
使用的是LinearSmoothScroller进行滑动操作,再来看LinearSmoothScroller类,它有一个获取滑动速度的方法:

protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
        return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
    }
所以我们可以想办法重写这个方法来改变RecyclerView滑动的速度。

我们自定义一个LinearLayoutManager:

public class ScrollLinearLayoutManager extends LinearLayoutManager {
    private static final float MILLISECONDS_PER_INCH = 25f;
    public ScrollLinearLayoutManager(Context context) {
        super(context);
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, final int position) {
        LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext())
        {

            @Nullable
            @Override
            public PointF computeScrollVectorForPosition(int targetPosition) {
                return ScrollLinearLayoutManager.this.computeScrollVectorForPosition(targetPosition);
            }

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

        };
        linearSmoothScroller.setTargetPosition(position);
        startSmoothScroll(linearSmoothScroller);
    }
}
重写smoothScrollToPosition()方法,然后重新实例化一个LinearSmoothScroller,并重写calculateSpeedPerPixel()方法, 
这样,可以调整MILLISECONDS_PER_INCH的值,来实现RecyclerView滑动速度的调整。

补充
由当前item到目标item的中间要滑动的item数量可能每次都不一样,这样固定的移动速度也会导致用户体验不好,所以可以根据需要滑动的item数量来动态的调整滑动速度, 
我们再修改下calculateSpeedPerPixel():

 protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                View view = getChildAt(0);
                if(view != null) {
                    final int firstChildPos = getPosition(getChildAt(0)); //获取当前item的position
                    int delta = Math.abs(position - firstChildPos);//算出需要滑动的item数量
                    if(delta == 0)
                        delta = 1;
                    return (MILLISECONDS_PER_INCH/delta) / displayMetrics.densityDpi;
                }
                else
                {
                    return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
                }

            }
这样当需要滑动的item数量越多,滑动速度越快,item数量少时,滑动会较慢,这样就会有一个好的用户体验。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值