對listview和recyclerview條目的展示和退出進行監聽

背景:

最近碰到一個需求,要統計列表中每個條目的總展示時長和單次最大展示時常,然後就在網上借鑑了不少代碼,整了個這玩意兒。

怎麼做:

  • 首先,需要實現對列表條目展示和退出的監聽,在某個條目進入屏幕的時候記錄一個時間戳,退出的時候再記錄一個,兩者的差值就是條目的展示時長

開始:

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);

分析代碼

  • 通過對列表的滾動進行監聽,獲取可見的最大和最小位置,與上次位置做比較進行判斷條目的進入和退出,回調結果

總結

一個有意思的工具類,平時開發應該很難用到,記錄一下以應對各種需求

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章