RecyclerView代码中滚动方法(滚动并置顶)

需求

  • 列表过长,点击浮动按钮使RecyclerView滚动返回置顶
  • 字母索引,快速滑动定位到某一个item并置顶

RecyclerView的原生方法

smoothScrollToPosition( int position )方法

滚动直到该Item完全可见
该方法的滚动有三种情况:

  1. 传入position在当前第一个可见项之前
    调用smoothScrollToPosition能够平滑的滚动到指定位置,并且置顶。

  2. 传入position在当前第一个可见项之后,并且在最后一个可见项之前
    调用smoothScrollToPosition,无动作,因为该项已经在屏幕中了。

  3. 传入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;// 这里是关键,得到的就是置顶的偏移量  
        }  
    }  
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章