(1)滾動(dòng)事件分類(lèi)
列表的滾動(dòng)一般分為兩種:
1.手指按下 -> 手指拖拽列表移動(dòng) -> 手指停止拖拽 -> 抬起手指
2.手指按下 -> 手指快速拖拽后抬起手指 -> 列表繼續(xù)滾動(dòng) -> 停止?jié)L動(dòng)
上面的過(guò)程的狀態(tài)變化如下:
1.靜止 -> 被迫拖拽移動(dòng) -> 靜止
2.靜止 -> 被迫拖拽移動(dòng) -> 自己滾動(dòng) -> 靜止
(2)監(jiān)聽(tīng)RecyclerView的滾動(dòng)
有兩種方式可以監(jiān)聽(tīng)滾動(dòng)事件:
1.setOnScrollListener(OnScrollListener listener)
2.addOnScrollListener(OnScrollListener listener)
其中 setOnScrollListener 由于可能出現(xiàn)空指針的風(fēng)險(xiǎn)鸭轮,已經(jīng)過(guò)時(shí)僧著。建議用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){}
}
OnScrollListener類(lèi)是個(gè)抽象類(lèi)艘款,有兩個(gè)方法:
void onScrollStateChanged(RecyclerView recyclerView, int newState): 滾動(dòng)狀態(tài)變化時(shí)回調(diào)
void onScrolled(RecyclerView recyclerView, int dx, int dy): 滾動(dòng)時(shí)回調(diào)
3.1 onScrollStateChanged(RecyclerView recyclerView, int newState)方法
回調(diào)的兩個(gè)變量的含義:
recyclerView: 當(dāng)前在滾動(dòng)的RecyclerView
newState: 當(dāng)前滾動(dòng)狀態(tài).
其中newState有三種值:
/**
* The RecyclerView is not currently scrolling.(靜止沒(méi)有滾動(dòng))
*/
public static final int SCROLL_STATE_IDLE = 0;
/**
* The RecyclerView is currently being dragged by outside input such as user touch input.
*(正在被外部拖拽,一般為用戶(hù)正在用手指滾動(dòng))
*/
public static final int SCROLL_STATE_DRAGGING = 1;
/**
* The RecyclerView is currently animating to a final position while not under outside control.
*(自動(dòng)滾動(dòng))
*/
public static final int SCROLL_STATE_SETTLING = 2;
3.2 onScrolled(RecyclerView recyclerView, int dx, int dy)方法
回調(diào)的三個(gè)變量含義:
recyclerView : 當(dāng)前滾動(dòng)的view
dx : 水平滾動(dòng)距離
dy : 垂直滾動(dòng)距離
dx > 0 時(shí)為手指向左滾動(dòng),列表滾動(dòng)顯示右面的內(nèi)容
dx < 0 時(shí)為手指向右滾動(dòng),列表滾動(dòng)顯示左面的內(nèi)容
dy > 0 時(shí)為手指向上滾動(dòng),列表滾動(dòng)顯示下面的內(nèi)容
dy < 0 時(shí)為手指向下滾動(dòng),列表滾動(dòng)顯示上面的內(nèi)容
(4)canScrollVertically和canScrollHorizontally方法
public boolean canScrollVertically (int direction)
這個(gè)方法是判斷View在豎直方向是否還能向上枫振,向下滑動(dòng)禽车。
其中窍蓝,direction為 -1 表示手指向下滑動(dòng)(屏幕向上滑動(dòng))啄刹, 1 表示手指向上滑動(dòng)(屏幕向下滑動(dòng))。
public boolean canScrollHorizontally (int direction)
這個(gè)方法用來(lái)判斷 水平方向的滑動(dòng)
例如:
RecyclerView.canScrollVertically(1)的值表示是否能向下滾動(dòng)焚辅,false表示已經(jīng)滾動(dòng)到底部
RecyclerView.canScrollVertically(-1)的值表示是否能向上滾動(dòng)映屋,false表示已經(jīng)滾動(dòng)到頂部
(5)兩種判斷是否到底部的方法:
5.1方法一:
如果 當(dāng)前
第一個(gè)可見(jiàn)item的位置 + 當(dāng)前可見(jiàn)的item個(gè)數(shù) >= item的總個(gè)數(shù)
這樣就可以判斷出來(lái),是在底部了同蜻。
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) //向下滾動(dòng)
{
int visibleItemCount = mLinearLayoutManager.getChildCount();
int totalItemCount = mLinearLayoutManager.getItemCount();
int pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition();
if (!loading && (visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = true;
loadMoreDate();
}
}
}
};
通過(guò)
visibleItemCount + pastVisiblesItems) >= totalItemCount
來(lái)判斷是否是底部棚点。
5.2方法二:
通過(guò)canScrollVertically 來(lái)判斷
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) //向下滾動(dòng)
// {
// int visibleItemCount = mLinearLayoutManager.getChildCount();
// int totalItemCount = mLinearLayoutManager.getItemCount();
// int pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition();
//
// if (!loading && (visibleItemCount + pastVisiblesItems) >= totalItemCount) {
// loading = true;
// loadMoreDate();
// }
// }
}
};
參考:
http://blog.devwiki.net/index.php/2016/06/13/RecyclerView-Scroll-Listener.html