1. 程式人生 > >RecyclerView程式碼中滾動方法(滾動並置頂)

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;// 這裡是關鍵,得到的就是置頂的偏移量  
        }  
    }  
}