RecyclerView的滚动事件OnScrollListener研究

bnrj7351 7年前
   <h2><strong>(1)滚动事件分类</strong></h2>    <p>列表的滚动一般分为两种:</p>    <pre>  <code class="language-java">1.手指按下 -> 手指拖拽列表移动 -> 手指停止拖拽 -> 抬起手指   2.手指按下 -> 手指快速拖拽后抬起手指 -> 列表继续滚动 -> 停止滚动</code></pre>    <p>上面的过程的状态变化如下:</p>    <pre>  <code class="language-java">1.静止 -> 被迫拖拽移动 -> 静止  2.静止 -> 被迫拖拽移动 -> 自己滚动 -> 静止</code></pre>    <h2><strong>(2)监听RecyclerView的滚动</strong></h2>    <p>有两种方式可以监听滚动事件:</p>    <pre>  <code class="language-java">1.setOnScrollListener(OnScrollListener listener)    2.addOnScrollListener(OnScrollListener listener)</code></pre>    <p>其中 setOnScrollListener 由于可能出现空指针的风险,已经过时。建议用addOnScrollListener。</p>    <h2><strong>(3)OnScrollListener</strong></h2>    <pre>  <code class="language-java">/**   * 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>    <p>OnScrollListener类是个抽象类,有两个方法:</p>    <pre>  <code class="language-java">void onScrollStateChanged(RecyclerView recyclerView, int newState): 滚动状态变化时回调  void onScrolled(RecyclerView recyclerView, int dx, int dy): 滚动时回调</code></pre>    <h3><strong>3.1 onScrollStateChanged(RecyclerView recyclerView, int newState)方法</strong></h3>    <p>回调的两个变量的含义:</p>    <p>recyclerView: 当前在滚动的RecyclerView</p>    <p>newState: 当前滚动状态.</p>    <p>其中newState有三种值:</p>    <pre>  <code class="language-java">/**   * 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>    <h3><strong>3.2 onScrolled(RecyclerView recyclerView, int dx, int dy)方法</strong></h3>    <p>回调的三个变量含义:</p>    <p>recyclerView : 当前滚动的view</p>    <p>dx : 水平滚动距离</p>    <p>dy : 垂直滚动距离</p>    <p>dx > 0时为手指向左滚动, <strong>列表滚动显示右面的内容</strong></p>    <p>dx < 0时为手指向右滚动, <strong>列表滚动显示左面的内容</strong></p>    <p>dy > 0时为手指向上滚动, <strong>列表滚动显示下面的内容</strong></p>    <p>dy < 0时为手指向下滚动, <strong>列表滚动显示上面的内容</strong></p>    <h2><strong>(4)canScrollVertically和canScrollHorizontally方法</strong></h2>    <pre>  <code class="language-java">public boolean canScrollVertically (int direction)  这个方法是判断View在竖直方向是否还能向上,向下滑动。  其中,direction为 -1 表示手指向下滑动(屏幕向上滑动), 1 表示手指向上滑动(屏幕向下滑动)。    public boolean canScrollHorizontally (int direction)  这个方法用来判断 水平方向的滑动</code></pre>    <p>例如:</p>    <p>RecyclerView.canScrollVertically(1)的值表示是否能向下滚动, <strong> <em>false表示已经滚动到底部</em> </strong></p>    <p>RecyclerView.canScrollVertically(-1)的值表示是否能向上滚动, <strong> <em>false表示已经滚动到顶部</em> </strong></p>    <h2><strong>(5)两种判断是否到底部的方法:</strong></h2>    <h3><strong>5.1方法一:</strong></h3>    <p>如果 当前</p>    <p><em>第一个可见item的位置 + 当前可见的item个数 >= item的总个数</em></p>    <p>这样就可以判断出来,是在底部了。</p>    <pre>  <code class="language-java">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>    <p>通过</p>    <p>visibleItemCount + pastVisiblesItems) >= totalItemCount</p>    <p>来判断是否是底部。</p>    <h3><strong>5.2方法二:</strong></h3>    <p>通过canScrollVertically 来判断</p>    <pre>  <code class="language-java">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>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/ce347cf991db</p>    <p> </p>