参考自:
//检测recyclerView的滚动事件
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
//关注:SCROLL_STATE_IDLE:停止滚动; SCROLL_STATE_DRAGGING: 用户慢慢拖动
// 关注:SCROLL_STATE_SETTLING:惯性滚动
if (newState == RecyclerView.SCROLL_STATE_IDLE
|| newState == RecyclerView.SCROLL_STATE_DRAGGING
|| newState == RecyclerView.SCROLL_STATE_SETTLING) {
handleCurrentVisibleItems();
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//包括刚进入列表时统计当前屏幕可见views
handleCurrentVisibleItems();
}
});
/**
* 处理 当前屏幕上mRecyclerView可见的item view
*/
public void handleCurrentVisibleItems() {
//1、View.getGlobalVisibleRect(new Rect()),true表示view视觉可见,无论可见多少。
if (mRecyclerView == null || mRecyclerView.getVisibility() != View.VISIBLE ||
!mRecyclerView.isShown() || !mRecyclerView.getGlobalVisibleRect(new Rect())) {
return;
}
//保险起见,为了不让统计影响正常业务,这里做下try-catch
try {
int[] range = new int[2];
int orientation = -1;
RecyclerView.LayoutManager manager = mRecyclerView.getLayoutManager();
if (manager instanceof LinearLayoutManager) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) manager;
range = findRangeLinear(linearLayoutManager);
orientation = linearLayoutManager.getOrientation();
} else if (manager instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) manager;
range = findRangeGrid(gridLayoutManager);
orientation = gridLayoutManager.getOrientation();
} else if (manager instanceof StaggeredGridLayoutManager) {
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) manager;
range = findRangeStaggeredGrid(staggeredGridLayoutManager);
orientation = staggeredGridLayoutManager.getOrientation();
}
if (range == null || range.length < 2) {
return;
}
XLogUtil.d("屏幕内可见条目的起始位置:" + range[0] + "---" + range[1]);
//2 注意,这里 会处理此刻 滑动过程中 所有可见的view
for (int i = range[0]; i <= range[1]; i++) {
View view = manager.findViewByPosition(i);
setCallbackForLogicVisibleView(view, i, orientation);
}
} catch (Exception e) {
e.printStackTrace();
XLogUtil.d(e.getMessage());
}
}
/**
* 为 逻辑上可见的view设置 可见性回调
* 说明:逻辑上可见--可见且可见高度(宽度)>view高度(宽度)的50%
* @param view 可见item的view
* @param position 可见item的position
* @param orientation recyclerView的方向
*/
private void setCallbackForLogicVisibleView(View view, int position, int orientation) {
if (view == null || view.getVisibility() != View.VISIBLE ||
!view.isShown() || !view.getGlobalVisibleRect(new Rect())) {
return;
}
Rect rect = new Rect();
boolean cover = view.getGlobalVisibleRect(rect);
//item逻辑上可见:可见且可见高度(宽度)>view高度(宽度)50%才行
boolean visibleHeightEnough = orientation == OrientationHelper.VERTICAL && rect.height() > view.getMeasuredHeight() / 2;
boolean visibleWidthEnough = orientation == OrientationHelper.HORIZONTAL && rect.width() > view.getMeasuredWidth() / 2;
boolean isItemViewVisibleInLogic = visibleHeightEnough || visibleWidthEnough;
if (cover && mIsRecyclerViewVisibleInLogic && isItemViewVisibleInLogic) {
mItemOnExposeListener.onItemViewVisible(true, position);
}else {
mItemOnExposeListener.onItemViewVisible(false, position);
}
}