需求
- 列表過長,點擊浮動按鈕使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;// 這裏是關鍵,得到的就是置頂的偏移量
}
}
}