背景:
最近碰到一個需求,要統計列表中每個條目的總展示時長和單次最大展示時常,然後就在網上借鑑了不少代碼,整了個這玩意兒。
怎麼做:
- 首先,需要實現對列表條目展示和退出的監聽,在某個條目進入屏幕的時候記錄一個時間戳,退出的時候再記錄一個,兩者的差值就是條目的展示時長
開始:
public class OnItemEnterOrExitVisibleHelper {
private int lastStart = -1;
private int lastEnd;
private SparseArray<Long> mLastRecordTime = new SparseArray<>();
private SparseArray<Long> mAllTime = new SparseArray<>();
private SparseArray<Long> mMaxTime = new SparseArray<>();
public interface OnScrollStatusListener {
void onSelectEnterPosition(int postion);
void onSelectExitPosition(int postion);
void onListStop();
}
public void dealScrollEvent(int firstVisible, int lastVisible) {
int visibleItemCount = lastVisible - firstVisible;
if (visibleItemCount > 0) {
if (lastStart == -1) {
lastStart = firstVisible;
lastEnd = lastVisible;
for (int i = lastStart; i < lastEnd + 1; i++) {
if (mScrollStatusListener != null) {
mScrollStatusListener.onSelectEnterPosition(i);
}
}
} else {
if (firstVisible != lastStart) {
if (firstVisible > lastStart) {//向上滑動
for (int i = lastStart; i < firstVisible; i++) {
if (mScrollStatusListener != null) {
mScrollStatusListener.onSelectExitPosition(i);
}
}
} else {//向下滑動
for (int i = firstVisible; i < lastStart; i++) {
if (mScrollStatusListener != null) {
mScrollStatusListener.onSelectEnterPosition(i);
}
}
}
lastStart = firstVisible;
}
//
if (lastVisible != lastEnd) {
if (lastVisible > lastEnd) {//向上滑動
for (int i = lastEnd; i < lastVisible; i++) {
if (mScrollStatusListener != null) {
mScrollStatusListener.onSelectEnterPosition(i + 1);
}
}
} else {//向下滑動
for (int i = lastVisible; i < lastEnd; i++) {
if (mScrollStatusListener != null) {
mScrollStatusListener.onSelectExitPosition(i + 1);
}
}
}
lastEnd = lastVisible;
}
}
}
}
public void registerItemEnterAndExitListener(ListView listView) {
listView.setOnScrollListener(listViewScrollListener);
}
public void registerItemEnterAndExitListener(RecyclerView recyclerView) {
recyclerView.addOnScrollListener(recyclerScrollListener);
}
private AbsListView.OnScrollListener listViewScrollListener = new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == 0 && mScrollStatusListener != null) {
mScrollStatusListener.onListStop();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int paramVisibleItemCount, int totalItemCount) {
int firstVisible = view.getFirstVisiblePosition();
int lastVisible = view.getLastVisiblePosition();
dealScrollEvent(firstVisible, lastVisible);
}
};
private RecyclerView.OnScrollListener recyclerScrollListener=new RecyclerView.OnScrollListener(){
//RecyclerVew
@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);
LinearLayoutManager layoutManager= (LinearLayoutManager) recyclerView.getLayoutManager();
if (layoutManager!=null){
int firstVisible = layoutManager.findFirstVisibleItemPosition();
int lastVisible = layoutManager.findLastVisibleItemPosition();
int visibleItemCount = lastVisible - firstVisible;
if (lastVisible == 0) {
visibleItemCount = 0;
}
if (visibleItemCount != 0) {
dealScrollEvent(firstVisible, lastVisible);
}
}
}
};
private OnScrollStatusListener mScrollStatusListener = new OnScrollStatusListener() {
public void onSelectEnterPosition(int position) {
if (position < 0) {
return;
}
mLastRecordTime.append(position, System.currentTimeMillis());
}
public void onSelectExitPosition(int position) {
if (position < 0) {
return;
}
Long time = mLastRecordTime.get(position);
if (time!=null&&time != 0) {
long gap = System.currentTimeMillis() - time;
if (mMaxTime.get(position) == null || mMaxTime.get(position) < gap) {
mMaxTime.append(position, gap);
}
mAllTime.append(position, gap +
(mAllTime.get(position) == null ? 0 : mAllTime.get(position)));
}
}
public void onListStop() {
}
};
}
使用方法
OnItemEnterOrExitVisibleHelper mOnItemEnterOrExitHelper
= new OnItemEnterOrExitVisibleHelper();
mOnItemEnterOrExitHelper.registerItemEnterAndExitListener(mListView);
分析代碼
- 通過對列表的滾動進行監聽,獲取可見的最大和最小位置,與上次位置做比較進行判斷條目的進入和退出,回調結果
總結
一個有意思的工具類,平時開發應該很難用到,記錄一下以應對各種需求