本以为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");
}
下面以双击返回列表顶部为例,实现方案是这样的:
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);
}