Android RecyclerView.smoothScrollToPosition()的实现

本以为RecyclerView会像ListView一样有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);
    }
然后继续往里点

public void smoothScrollToPosition(RecyclerView recyclerView, State state,
                int position) {
            Log.e(TAG, "You must override smoothScrollToPosition to support smooth scrolling");
        }

SDK居然没有给出这个方法的实现,还让我们自己复写这个方法来实现,真是太坑了,于是我只能自己去复写RecyclerView的smoothScrollToPosition方法了。

下面以双击返回列表顶部为例,实现方案是这样的:

1、首先计算要滚动的距离,如果你的item元素每个都是一样高的,那么计算起来就非常简单,只需要用每个元素的高度乘现在屏幕低端是第几个就好,如果每个item的高度是不定,那么就需要依次计算相加,一般用measure()方法

2、知道要滚动的距离之后,调用smoothScrollBy方法滚动这段距离,然后滚回顶部就可以了。

现在问题来了,如果我知道要滚动的距离是多少,我还要smotthScrollToPositon这个方法干嘛,直接用smoothScrollBy不就好了。所以我们现在不需要知道每个item具体的高度是多少,只需要大概能估摸出来就行。

所以现在变成了

1、首先估摸一下大概要滚动多少距离,然后挑一个绝对会大于该滚动距离的值,使用smoothScrollBy进行滚动

2、设置onScrollListener监听滚动事件,当滚动到目标地址以后立即刹车停住。

其中估摸的滚动距离要大于实际的滚动距离,但是也不要大太多,虽然这个值只要比实际滚动距离大就可以实现滚动到指定位置,但是偏离值越大速度就越快,很可能看不清滚动效果。

代码如下,方法名是scrollUpToPosition()用来向上滚,实现双击返回列表顶部的效果

 public void smoothScrollUpToPosition(final int position, int itemHeight){
        int height = (layoutManager.findLastVisibleItemPositon())*itemHeight;
        this.addOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();//获得屏幕第一个可见元素的位置
                if (firstVisibleItem == position + 1) {
                    smoothScrollBy(0, 0);//刹车,停止当前滚动
                    removeOnScrollListener(this);
                }

            }
        });
        this.smoothScrollBy(0,-height);
    }

调用方法

RecyclerView.smoothScrollUpToPosition(1, getScreenHeigth()/2)
其中第二个参数是每个item的估计高度,我这里估计屏幕高度的一半,这个高度要大于滚动


如果是向下滚,可以使用下面这段代码:


public void smoothScrollDownToPosition(final int position, int itemHeight){
        int height = (layoutManager.findLastVisibleItemPosition())*itemHeight;
        this.addOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                int lastVisibleItem = layoutManager.findLastVisibleItemPosition();
                if (lastVisibleItem == position + 1) {
                    smoothScrollBy(0, 0);
                    removeOnScrollListener(this);
                }

            }
        });
        this.smoothScrollBy(0,height);
    }



你可能感兴趣的:(Android RecyclerView.smoothScrollToPosition()的实现)