Android ListView以及RecyclerView里面 监听Item可见以及不可见的状态

项目开发中最近 经常遇到这样的需求,就是ListView或者RecyclerView中的ItemView 被展示或者不可见的时候 要被能监听到

这个通常是打点的需求。

 

这里我们能想到的是 滚动的监听,无论是ListView或者RecyclerView的监听事件

要监听的就是第一个显示的position以及最后显示的position,然后对比上次显示的第一个position和最后一个position。

对比之后我们就可以知道 哪些范围的position退出了,哪些范围的position新进来的。

 

1、ListView的监听

 private AbsListView.OnScrollListener listiewScrollListener=new AbsListView.OnScrollListener(){
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {

        }
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int paramVisibleItemCount, int totalItemCount) {
            int firstVisible = view.getFirstVisiblePosition();
            int lastVisible = view.getLastVisiblePosition();
            dealScrollEvent(firstVisible, lastVisible);
        }
    };

2、RecyclerView滚动的监听

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

RecyclerView的fistPosition是通过LayoutManager获取到的,我们还需要注意的是

 //此方法常用作判断是否能下拉刷新,来解决滑动冲突
//int findFirstCompletelyVisibleItemPosition = layoutManager.findFirstCompletelyVisibleItemPosition();
//最后一个完整的可见的item位置
//int findLastCompletelyVisibleItemPosition = layoutManager.findLastCompletelyVisibleItemPosition();

获取完整的显示的view,这个跟或者position还是有差别的

 int firstVisible = layoutManager.findFirstVisibleItemPosition();
 int lastVisible = layoutManager.findLastVisibleItemPosition();

我们要精确的获取view的位置状态。

 

3 、我们获取到监听之后 就要分析

 private 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 (listener!=null){
                        listener.onSelectEnterPosition(i);
                    }

                }
            } else {
                if (firstVisible != lastStart) {
                    if (firstVisible > lastStart) {//向上滑动
                        for (int i = lastStart; i < firstVisible; i++) {
                            if (listener!=null){
                                listener.onSelectExitPosition(i);
                            }
                        }
                    } else {//向下滑动
                        for (int i = firstVisible; i < lastStart; i++) {
                            if (listener!=null){
                                listener.onSelectEnterPosition(i);
                            }
                        }
                    }
                    lastStart = firstVisible;
                }
                //
                if (lastVisible != lastEnd) {
                    if (lastVisible > lastEnd) {//向上滑动
                        for (int i = lastEnd; i < lastVisible; i++) {
                            if (listener!=null){
                                listener.onSelectEnterPosition(i + 1);
                            }

                        }
                    } else {//向下滑动
                        for (int i = lastVisible; i < lastEnd; i++) {
                            if (listener!=null){
                                listener.onSelectExitPosition(i + 1);
                            }
                        }
                    }
                    lastEnd = lastVisible;
                }
            }
        }
    }

我们设置了两个回调,一个是进入的回调,一个是退出的回调

listener.onSelectEnterPosition(i);

listener.onSelectExitPosition(i);

Android ListView以及RecyclerView里面 监听Item可见以及不可见的状态

  OnItemEnterOrExitVisibleHelper helper = new OnItemEnterOrExitVisibleHelper();

  helper.setListiewScrollListener(listview);
  helper.setOnScrollStatusListener(listener);
   



    private OnItemEnterOrExitVisibleHelper.OnScrollStatusListener listener = new OnItemEnterOrExitVisibleHelper.OnScrollStatusListener() {
        public void onSelectEnterPosition(int postion) {
            Log.v("xhw", "进入Enter:" + postion);
        }
        public void onSelectExitPosition(int postion) {
            Log.v("xhw", "退出Exit:" + postion);
        }
    };

github:https://github.com/xuhuawei131/RecyclerViewItemVisible