需求
- 列表过长,点击浮动按钮使RecyclerView滚动返回置顶
- 字母索引,快速滑动定位到某一个item并置顶
RecyclerView的原生方法
smoothScrollToPosition( int position )方法
滚动直到该Item完全可见
该方法的滚动有三种情况:
传入position在当前第一个可见项之前
调用smoothScrollToPosition能够平滑的滚动到指定位置,并且置顶。传入position在当前第一个可见项之后,并且在最后一个可见项之前
调用smoothScrollToPosition,无动作,因为该项已经在屏幕中了。传入position在当前最后一个可见项之后
调用smoothScrollToPosition,会有滑动,但是该item出现在屏幕底部就停止了。
smoothScrollBy( int dx, int dy )方法
根据滑动dy距离
第一个需求
调用RecyclerView的smoothScrollToPosition(0);
mRecyclerView.smoothScrollToPosition(0);
第二个需求
方法一 通过smoothScrollToPosition结合smoothScrollBy实现
//ex.
smoothScrollToPosition(20);
private boolean mShouldScroll;
private int mToPosition;
private void smoothMoveToPosition(final int position) {
int firstItem = mPhotosRV.getChildLayoutPosition(mPhotosRV.getChildAt(0));
int lastItem = mPhotosRV.getChildLayoutPosition(mPhotosRV.getChildAt(mPhotosRV.getChildCount() -1));
if (position < firstItem ) {
// 如果要跳转的位置在第一个可见项之前,则smoothScrollToPosition可以直接跳转
mPhotosRV.smoothScrollToPosition(position);
} else if (position <= lastItem) {
// 如果要跳转的位置在第一个可见项之后,且在最后一个可见项之前
// smoothScrollToPosition根本不会动,
// 通过计算要跳转的item的top,然后在使用smoothScrollBy进行跳转
int movePosition = position - firstItem;
if (movePosition >= 0 && movePosition < mPhotosRV.getChildCount()) {
int top = mPhotosRV.getChildAt(movePosition).getTop();
mPhotosRV.smoothScrollBy(0, top);
}
} else {
// 如果要跳转的位置在最后可见项之后,则先调用smoothScrollToPosition让要跳转的item位于屏幕可见范围之内,然后再通过smoothScrollBy进行跳转
// 再通过onScrollStateChanged控制再次调用smoothMoveToPosition,进入上一个控制语句
mPhotosRV.smoothScrollToPosition(position);
mShouldScroll = true;
mToPosition = position;
}
}
private RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
// mAutoScrolling = false;
if (mShouldScroll) {
mShouldScroll = false;
smoothMoveToPosition(mToPosition);
}
}
}
};
第二种方法 TopLayoutManager替换LinearLayoutManager
//ex.
TopLayoutManager manager=new TopLayoutManager(this);
mRecyclerView.setLayoutManager(manager);
//TopLayoutManager
public class TopLayoutManager extends LinearLayoutManager {
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
RecyclerView.SmoothScroller smoothScroller = new TopSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
private class TopSmoothScroller extends LinearSmoothScroller {
TopSmoothScroller(Context context) {
super(context);
}
/**
* 以下参数以LinearSmoothScroller解释
* @param viewStart RecyclerView的top位置
* @param viewEnd RecyclerView的bottom位置
* @param boxStart Item的top位置
* @param boxEnd Item的bottom位置
* @param snapPreference 判断滑动方向的标识(The edge which the view should snap to when entering the visible
* area. One of {@link #SNAP_TO_START}, {@link #SNAP_TO_END} or
* {@link #SNAP_TO_END}.)
* @return 移动偏移量
*/
@Override
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
return boxStart - viewStart;// 这里是关键,得到的就是置顶的偏移量
}
}
}