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