RecyclerView的滾動事件OnScrollListener研究

bnrj7351 8年前發布 | 76K 次閱讀 Android開發 移動開發 RecyclerView

(1)滾動事件分類

列表的滾動一般分為兩種:

1.手指按下 -> 手指拖拽列表移動 -> 手指停止拖拽 -> 抬起手指
 2.手指按下 -> 手指快速拖拽后抬起手指 -> 列表繼續滾動 -> 停止滾動

上面的過程的狀態變化如下:

1.靜止 -> 被迫拖拽移動 -> 靜止
2.靜止 -> 被迫拖拽移動 -> 自己滾動 -> 靜止

(2)監聽RecyclerView的滾動

有兩種方式可以監聽滾動事件:

1.setOnScrollListener(OnScrollListener listener)
  2.addOnScrollListener(OnScrollListener listener)

其中 setOnScrollListener 由于可能出現空指針的風險,已經過時。建議用addOnScrollListener。

(3)OnScrollListener

/**

  • An OnScrollListener can be added to a RecyclerView to receive messages when a scrolling event
  • has occurred on that RecyclerView.
  • <p>
  • @see RecyclerView#addOnScrollListener(OnScrollListener)
  • @see RecyclerView#clearOnChildAttachStateChangeListeners() / public abstract static class OnScrollListener { /**

    • Callback method to be invoked when RecyclerView's scroll state changes. *
    • @param recyclerView The RecyclerView whose scroll state has changed.
    • @param newState The updated scroll state. One of {@link #SCROLL_STATE_IDLE},
    • {@link #SCROLL_STATE_DRAGGING} or {@link #SCROLL_STATE_SETTLING}. */ public void onScrollStateChanged(RecyclerView recyclerView, int newState){}

      /**

    • Callback method to be invoked when the RecyclerView has been scrolled. This will be
    • called after the scroll has completed.
    • <p>
    • This callback will also be called if visible item range changes after a layout
    • calculation. In that case, dx and dy will be 0. *
    • @param recyclerView The RecyclerView which scrolled.
    • @param dx The amount of horizontal scroll.
    • @param dy The amount of vertical scroll. */ public void onScrolled(RecyclerView recyclerView, int dx, int dy){} }</code></pre>

      OnScrollListener類是個抽象類,有兩個方法:

      void onScrollStateChanged(RecyclerView recyclerView, int newState): 滾動狀態變化時回調
      void onScrolled(RecyclerView recyclerView, int dx, int dy): 滾動時回調

      3.1 onScrollStateChanged(RecyclerView recyclerView, int newState)方法

      回調的兩個變量的含義:

      recyclerView: 當前在滾動的RecyclerView

      newState: 當前滾動狀態.

      其中newState有三種值:

      /**
  • The RecyclerView is not currently scrolling.(靜止沒有滾動) */ public static final int SCROLL_STATE_IDLE = 0;

/**

  • The RecyclerView is currently being dragged by outside input such as user touch input. (正在被外部拖拽,一般為用戶正在用手指滾動)/ public static final int SCROLL_STATE_DRAGGING = 1;

/**

  • The RecyclerView is currently animating to a final position while not under outside control. (自動滾動)/ public static final int SCROLL_STATE_SETTLING = 2;</code></pre>

    3.2 onScrolled(RecyclerView recyclerView, int dx, int dy)方法

    回調的三個變量含義:

    recyclerView : 當前滾動的view

    dx : 水平滾動距離

    dy : 垂直滾動距離

    dx > 0時為手指向左滾動, 列表滾動顯示右面的內容

    dx < 0時為手指向右滾動, 列表滾動顯示左面的內容

    dy > 0時為手指向上滾動, 列表滾動顯示下面的內容

    dy < 0時為手指向下滾動, 列表滾動顯示上面的內容

    (4)canScrollVertically和canScrollHorizontally方法

    public boolean canScrollVertically (int direction)
    這個方法是判斷View在豎直方向是否還能向上,向下滑動。
    其中,direction為 -1 表示手指向下滑動(屏幕向上滑動), 1 表示手指向上滑動(屏幕向下滑動)。

public boolean canScrollHorizontally (int direction) 這個方法用來判斷 水平方向的滑動</code></pre>

例如:

RecyclerView.canScrollVertically(1)的值表示是否能向下滾動, false表示已經滾動到底部

RecyclerView.canScrollVertically(-1)的值表示是否能向上滾動, false表示已經滾動到頂部

(5)兩種判斷是否到底部的方法:

5.1方法一:

如果 當前

第一個可見item的位置 + 當前可見的item個數 >= item的總個數

這樣就可以判斷出來,是在底部了。

loadingMoreListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);

        if (dy > 0) //向下滾動
        {
            int visibleItemCount = mLinearLayoutManager.getChildCount();
            int totalItemCount = mLinearLayoutManager.getItemCount();
            int pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition();

            if (!loading && (visibleItemCount + pastVisiblesItems) >= totalItemCount) {
                loading = true;
                loadMoreDate();
            }
        }
    }

};</code></pre>

通過

visibleItemCount + pastVisiblesItems) >= totalItemCount

來判斷是否是底部。

5.2方法二:

通過canScrollVertically 來判斷

loadingMoreListener = new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        if(!loading && !recyclerView.canScrollVertically(1)){
            loading = true;
            loadMoreDate();
        }
    }

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);

// if (dy > 0) //向下滾動 // { // int visibleItemCount = mLinearLayoutManager.getChildCount(); // int totalItemCount = mLinearLayoutManager.getItemCount(); // int pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition(); // // if (!loading && (visibleItemCount + pastVisiblesItems) >= totalItemCount) { // loading = true; // loadMoreDate(); // } // } } };</code></pre>

 

 

來自:http://www.jianshu.com/p/ce347cf991db

 

 本文由用戶 bnrj7351 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!