Android ListView获取当前可视区域条目数据

来源:互联网 发布:淘宝出售可非大力小泰 编辑:程序博客网 时间:2024/06/06 01:00

最近在项目中接到一个很奇葩的数据统计需求。

根据出现在屏幕中可视区域内的控件,来上报数据统计。当控件出现可视范围内,则统计相应的数据。如果界面上有多个需要统计的控件,则需要过滤掉上一次出现在可视区域内的数据。如果滑出屏幕可视区域了,再次进入则又要统计。

在网上找也没有找到跟这些相关的,最多就是找到获取ListView当前区域的数据。最后在百度知道里面找一个差不多类似的,根据里面的思路来改的。

@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {    // TODO Auto-generated method stub    if (performanceWidgetTicket != null && mLiveShowTicketList != null) {//这行代码是我的数据操作所需要的null判断,可换成你需要的条件        // 比较两次可见的item的序号,只曝光新出现的        ArrayList<Integer> list = new ArrayList<Integer>(visibleItemCount);        // 将最新可见item的index加入到临时list中        for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) {            list.add(i);        }        if (visibleList != null && list != null) {            //新可见item的index的集合            ArrayList<Integer> diffList = getDiffrent(list, visibleList);            if (diffList != null) {                for (int x = 0; x < diffList.size(); x++) {                    // 曝光操作                    // 在这里做相应操作                    LogUtils.LOGD(TAG, "diffList.get(x):" + diffList.get(x));                }                //更新list,将最新的可见item的index加入到list                visibleList.clear();                visibleList.addAll(list);            }        }        //清空最新可见item的index的list        if (list != null) {            list.clear();        }    }}

上面的代码是在百度知道里面找的。思路也是跟一样。其实这块并不难,难点在于查找数据方面。因为我有多个界面需要统计,所以每个界面处理都不一样,但思路是一样的。
首页1
首页2
因为首页有两种条目需要上报的,所以处理也是需要结合两种条目的处理方式一起处理。

下面这个是取出两个list中不同的元素加入到新的list

public static ArrayList<Integer> getDiffrent(List<Integer> list1, List<Integer> list2) {    long st = System.nanoTime();    ArrayList<Integer> diff = new ArrayList<Integer>();        for (Integer index : list1) {            if (!list2.contains(index)) {                diff.add(index);            }        }    return diff;}

这下面是首页获取统计的主要方法了,我的统计是在滑动停止之后,而不是滑动中所以跟上面代码会有点区别,最主要的就在于获取下标的问题上面。就是第一个循环处

    /** 存放可见的ListView */    public List<Integer> visibleList = new ArrayList<Integer>();    /** 获取Holder并且上报 */    public void gameInfoExposure() {        int firstVisible = content.getFirstVisiblePosition();        int lastVisible = content.getLastVisiblePosition();        int index = content.getHeaderViewsCount();        Map<String, Object> mapList = new HashMap<String, Object>();        // 需要上报的游戏Id集合        List<String> gameIds = new ArrayList<String>();        // 将最新可见item的index加入到临时list中        ArrayList<Integer> list = new ArrayList<Integer>();        // 标识是否提交信息        boolean isSubmit = false;        // 遍历的时候下标要减一个        for (int i = firstVisible - 1; i < lastVisible; i++) {            View tmp = content.getChildAt((index + i) - firstVisible - 1);            if (tmp != null) {                Object tag = tmp.getTag();                // 这里要判断两个类型的条目                if (tag != null && tag instanceof HomeGameGridViewItemHolder) {                    // 这里是宫格Item的                    HomeGameGridViewItemHolder holder = (HomeGameGridViewItemHolder) tag;                    GameGridViewItemHolder gameItem = getGameItemHolder(holder, 0);                    // 得到第一个Holder下载控件的View,并且判断是否可见                    View downloadView = gameItem.getDownloadView();                    Rect scrollBounds = new Rect();                    downloadView.getHitRect(scrollBounds);                    if (downloadView.getLocalVisibleRect(scrollBounds)) {                        list.add(i);                        mapList.put(i + "", holder);                    }                } else if (tag != null && tag instanceof RedGameHolder) {                    // 正常Item                    RedGameHolder holder = (RedGameHolder) tag;                    // 获取下载控件,并且判断是否可见                    View downloadView = holder.getDownloadView();                    Rect scrollBounds = new Rect();                    downloadView.getHitRect(scrollBounds);                    // 判断View是否移出去了不可见或者可见                    if (downloadView.getLocalVisibleRect(scrollBounds)) {                        // View 进入当前屏幕可视,哪怕一个像素                        list.add(i);//                      RedGameBean gameBean = holder.getGameBean();                        mapList.put(i + "", holder);                    }                }            }        }        // 新可见item的index的集合        ArrayList<Integer> diffList = DataHelper.getDiffrent(list, visibleList);        if (!diffList.isEmpty()) {            for (Integer i : diffList) {                Object obj = mapList.get("" + i);                if (obj != null && obj instanceof HomeGameGridViewItemHolder) {                    // 在这里需要再次反向查找对应View是在可视区域内                    HomeGameGridViewItemHolder holder = (HomeGameGridViewItemHolder) obj;                    int count = holder.getGridView().getAdapter().getCount();                    for (int j = 0; j < count; j++) {                        GameGridViewItemHolder item = getGameItemHolder(holder, j);                        if (!FileHelper.checkApkExist(mActivity, item.getGameBean().getLocalApkName())) {                            String str = item.getGameBean().getType() + ":" + item.getGameBean().getId();                            gameIds.add(str);                            isSubmit = true;                        }                    }                } else if (obj != null && obj instanceof RedGameHolder) {                    RedGameHolder holder = (RedGameHolder) obj;                    RedGameBean gameBean = holder.getGameBean();                    if (gameBean != null && !FileHelper.checkApkExist(mActivity, gameBean.getLocalApkName())) {                        String str = gameBean.getType() + ":" + gameBean.getId();                        gameIds.add(str);                        isSubmit = true;                    }                }            }        }        // 更新list,将最新的可见item的index加入到list        visibleList.clear();        visibleList.addAll(list);        // 清除Map集合        if (!mapList.isEmpty()) {            mapList.clear();        }        // 清空最新可见item的index的list        if (!list.isEmpty()) {            list.clear();        }        if (isSubmit) {            String ids = "";            if (gameIds.size() > 0) {                for (int i = 0; i < gameIds.size(); i++) {                    ids = ids + gameIds.get(i);                    if (i != gameIds.size() - 1)                        ids = ids + "|";                }                // 这里执行上报                // 该处就是执行你代码提交的地方了                gameIds.clear();            }            isSubmit = false;        }    }

下面就是同一个界面获取同样条目的统计数据了,在这个统计方法里面思路跟上面是一样的,只不过Map集合存的对象我换了而已。
先上个界面列表页

    /** 存放可见的ListView */    private List<Integer> visibleList = new ArrayList<Integer>();    /** 获取Holder并且上报 */    private void gameInfoExposure() {        // TODO        int firstVisible = listView.getFirstVisiblePosition();        int lastVisible = listView.getLastVisiblePosition();        int index = listView.getHeaderViewsCount();        // 加载的数据类型,1为分类,默认为0榜单        int type = loadDataType == 1 ? 1 : 0;        Map<String, RedGameBean> mapList = new HashMap<String, RedGameBean>();        // 需要上报的游戏Id集合        List<String> gameIds = new ArrayList<String>();        // 将最新可见item的index加入到临时list中        ArrayList<Integer> list = new ArrayList<Integer>();        // 标识是否提交游戏信息        boolean isSubmit = false;        int count = firstVisible > 0 ? firstVisible - 1 : 0;        // 遍历的时候下标要减一个,不然会有问题        for (int i = count - 1; i <= lastVisible; i++) {            View tmp = listView.getChildAt((index + i) - firstVisible);            if (tmp != null) {                Object tag = tmp.getTag();                if (tag != null && tag instanceof RedGameHolder) {                    RedGameHolder holder = (RedGameHolder) tag;                    // 获取下载控件,并且判断是否可见                    View downloadView = holder.getDownloadView();                    Rect scrollBounds = new Rect();                    downloadView.getHitRect(scrollBounds);                    // 判断View是否移出去了不可见或者可见                    if (downloadView.getLocalVisibleRect(scrollBounds)) {                        // View 进入当前屏幕可视,哪怕一个像素                        list.add(i);                        RedGameBean gameBean = holder.getGameBean();                        mapList.put("" + i, gameBean);                    }                }            }        }        // 新可见item的index的集合        ArrayList<Integer> diffList = DataHelper.getDiffrent(list, visibleList);        if (!diffList.isEmpty()) {            for (Integer i : diffList) {                RedGameBean gameBean = mapList.get("" + i);                if (gameBean != null && !FileHelper.checkApkExist(mActivity, gameBean.getLocalApkName())) {                    String str = AppDefine.NA + ":" + gameBean.getId();                    gameIds.add(str);                    isSubmit = true;                }            }        }        // 更新list,将最新的可见item的index加入到list        visibleList.clear();        visibleList.addAll(list);        // 清除Map集合        if (!mapList.isEmpty()) {            mapList.clear();        }        // 清空最新可见item的index的list        if (!list.isEmpty()) {            list.clear();        }        if (isSubmit) {            String ids = "";            if (gameIds.size() > 0) {                for (int i = 0; i < gameIds.size(); i++) {                    ids = ids + gameIds.get(i);                    if (i != gameIds.size() - 1)                        ids = ids + "|";                }                // 这里执行上报                // 该处就是执行你代码提交的地方了                gameIds.clear();            }            isSubmit = false;        }    }

下面的代码就是自己备忘的了,有需要的同鞋也可以参照着改哈。思路完全是跟上面的一样,只不过界面不一样了而已
搜索1

    /** 存放可见的ListView */    private List<Integer> visibleList = new ArrayList<Integer>();    /** 获取游戏Holder并且上报游戏曝光 */    private void gameInfoExposure() {        // TODO 这个界面因为别人实现的,只能根据封装的界面去反向查找,界面看上去像一个ListView其实里面有包含有多个子ListView,所以需要拿拿到对应的Holder再找到里面的ListView再次查找        int firstVisible = searchListview.getFirstVisiblePosition();        int lastVisible = searchListview.getLastVisiblePosition();        int index = searchListview.getHeaderViewsCount();        Map<String, RedGameBean> mapList = new HashMap<String, RedGameBean>();        // 需要上报的游戏Id集合        List<String> gameIds = new ArrayList<String>();        // 将最新可见item的index加入到临时list中        ArrayList<Integer> list = new ArrayList<Integer>();        // 标识是否提交游戏信息        boolean isSubmit = false;//      int count = firstVisible > 0 ? firstVisible - 1 : 0;        // 遍历的时候下标要减一个,不然会有问题        for (int i = firstVisible; i <= lastVisible; i++) {            View tmp = searchListview.getChildAt((index + i) - firstVisible);            if (tmp != null) {                Object tag = tmp.getTag();                // 如果不是游戏条目则就不进入了                if (tag != null && tag instanceof SearchRedGameHolder) {                    SearchRedGameHolder holder = (SearchRedGameHolder) tag;                    ListView lv = holder.getListView();                    if(lv != null){                        int lvFirstVisible = lv.getFirstVisiblePosition();                        int lvLastVisible = lv.getLastVisiblePosition();                        int lvIndex = lv.getHeaderViewsCount();                        // 这里进行第二次遍历                        for (int j = lvFirstVisible; j <= lvLastVisible; j++) {                            View view = lv.getChildAt((lvIndex + j) - firstVisible);                            if (view != null) {                                Object viewTag = view.getTag();                                if (viewTag != null && viewTag instanceof RedGameHolder) {                                    RedGameHolder gameHolder = (RedGameHolder) viewTag;                                    View downloadView = gameHolder.getDownloadView();                                    Rect scrollBounds = new Rect();                                    downloadView.getHitRect(scrollBounds);                                    // 判断View是否移出去了不可见或者可见                                    if (downloadView.getLocalVisibleRect(scrollBounds)) {                                        // View 进入当前屏幕可视,哪怕一个像素                                        list.add(j);                                        RedGameBean gameBean = gameHolder.getGameBean();                                        mapList.put("" + j, gameBean);                                    }                                }                            }                        }                    }                }            }        }        // 新可见item的index的集合        ArrayList<Integer> diffList = DataHelper.getDiffrent(list, visibleList);        if (!diffList.isEmpty()) {            for (Integer i : diffList) {                RedGameBean gameBean = mapList.get("" + i);                // 判断游戏是否安装                if (gameBean != null && !FileHelper.checkApkExist(mActivity, gameBean.getLocalApkName())) {                    String str = AppDefine.NA + ":" + gameBean.getId();                    gameIds.add(str);                    isSubmit = true;                }            }        }        // 更新list,将最新的可见item的index加入到visibleList        visibleList.clear();        visibleList.addAll(list);        // 清除Map集合        if (!mapList.isEmpty()) {            mapList.clear();        }        // 清空最新可见item的index的list        if (!list.isEmpty()) {            list.clear();        }        if (isSubmit) {            String ids = "";            if (gameIds.size() > 0) {                for (int i = 0; i < gameIds.size(); i++) {                    ids = ids + gameIds.get(i);                    if (i != gameIds.size() - 1)                        ids = ids + "|";                }                // 这里执行上报                gameIds.clear();            }            isSubmit = false;        }    }

搜索结果更多

    更多界面重跟列表一样就行了    /** 存放可见的ListView */    private List<Integer> visibleList = new ArrayList<Integer>();    /** 获取游戏Holder并且上报游戏曝光 */    private void gameInfoExposure() {        int firstVisible = searchListview.getFirstVisiblePosition();        int lastVisible = searchListview.getLastVisiblePosition();        int index = searchListview.getHeaderViewsCount();        Map<String, RedGameBean> mapList = new HashMap<String, RedGameBean>();        // 需要上报的游戏Id集合        List<String> gameIds = new ArrayList<String>();        // 将最新可见item的index加入到临时list中        ArrayList<Integer> list = new ArrayList<Integer>();        // 标识是否提交游戏信息        boolean isSubmit = false;        int count = firstVisible > 0 ? firstVisible - 1 : 0;        // 遍历的时候下标要减一个,不然会有问题        for (int i = count; i <= lastVisible; i++) {            View tmp = searchListview.getChildAt((index + i) - firstVisible -2);            if (tmp != null) {                Object tag = tmp.getTag();                if (tag != null && tag instanceof RedGameHolder) {                    RedGameHolder holder = (RedGameHolder) tag;                    // 获取下载控件,并且判断是否可见                    View downloadView = holder.getDownloadView();                    Rect scrollBounds = new Rect();                    downloadView.getHitRect(scrollBounds);                    // 判断View是否移出去了不可见或者可见                    if (downloadView.getLocalVisibleRect(scrollBounds)) {                        // View 进入当前屏幕可视,哪怕一个像素                        list.add(i);                        RedGameBean gameBean = holder.getGameBean();                        mapList.put("" + i, gameBean);                    }                }            }        }        // 新可见item的index的集合        ArrayList<Integer> diffList = DataHelper.getDiffrent(list, visibleList);        if (!diffList.isEmpty()) {            for (Integer i : diffList) {                RedGameBean gameBean = mapList.get("" + i);                if (gameBean != null && !FileHelper.checkApkExist(mActivity, gameBean.getLocalApkName())) {                    String str = AppDefine.NA + ":" + gameBean.getId();                    gameIds.add(str);                    isSubmit = true;                }            }        }        // 更新list,将最新的可见item的index加入到list        visibleList.clear();        visibleList.addAll(list);        // 清除Map集合        if (!mapList.isEmpty()) {            mapList.clear();        }        // 清空最新可见item的index的list        if (!list.isEmpty()) {            list.clear();        }        if (isSubmit) {            String ids = "";            if (gameIds.size() > 0) {                for (int i = 0; i < gameIds.size(); i++) {                    ids = ids + gameIds.get(i);                    if (i != gameIds.size() - 1)                        ids = ids + "|";                }                // 这里执行上报                gameIds.clear();            }            isSubmit = false;        }    }

详情推荐

这个界面只需要取其中的一条,所以处理也类似,并且View是GridView所以就没像上面那样处理了。    /** 存放可见的ListView */    private List<Integer> visibleList = new ArrayList<Integer>();    /** 获取游戏Holder并且上报游戏曝光 */    private void gameInfoExposure() {        int firstVisible = listView.getFirstVisiblePosition();        int lastVisible = listView.getLastVisiblePosition();        // int index = listView.getHeaderViewsCount();        // 需要上报的游戏Id集合        List<String> gameIds = new ArrayList<String>();        // 将最新可见item的index加入到临时list中        ArrayList<Integer> list = new ArrayList<Integer>();        // 标识是否提交游戏信息        boolean isSubmit = false;        // 遍历的时候下标要减一个,不然会有问题        for (int i = firstVisible; i <= lastVisible; i++) {            View tmp = listView.getChildAt(i - firstVisible);            if (tmp != null) {                Object tag = tmp.getTag();                if (tag != null && tag instanceof GameDetailRelatedHolder) {                    GameDetailRelatedHolder holder = (GameDetailRelatedHolder) tag;                    // 得到第一个GridView的Holder,有时候可能为空,下面要做判断                    GameGridViewItemHolder gameItem = getGameItemHolder(holder, 0);                    Rect scrollBounds = new Rect();                    // 得到第一个下载控件的View,并且判断是否可见                    View downloadView = gameItem.getDownloadView();                    downloadView.getHitRect(scrollBounds);                    if (downloadView.getLocalVisibleRect(scrollBounds)) {                        list.add(i);                        // 新可见item的index的集合,这个是用来做操作的。                        ArrayList<Integer> diffList = DataHelper.getDiffrent(list, visibleList);                        if (diffList.size() > 0) {                            // 重新获取可见的                            GridView gView = holder.getGridView();                            int count = gView.getAdapter().getCount();                            for (int j = 0; j < count; j++) {                                GameGridViewItemHolder item = getGameItemHolder(holder, j);                                if (!FileHelper.checkApkExist(mActivity, item.getGameBean().getLocalApkName())) {                                    String str = AppDefine.NA + ":" + item.getGameBean().getId();                                    gameIds.add(str);                                    isSubmit = true;                                }                            }                        }                        // 更新list,将最新的可见item的index加入到list                        visibleList.clear();                        visibleList.addAll(list);                    } else {                        // 清空可见视图集合                        visibleList.clear();                    }                }            }        }        // 清空最新可见item的index的list        if (list != null) {            list.clear();        }        if (isSubmit) {            String ids = "";            if (gameIds.size() > 0) {                for (int i = 0; i < gameIds.size(); i++) {                    ids = ids + gameIds.get(i);                    if (i != gameIds.size() - 1)                        ids = ids + "|";                }                // 这里执行上报                gameIds.clear();            }            isSubmit = false;        }    }

游戏帖子详情

详情界面数据是在ListViewHeader里面在里面又封装了个ListView。所以查找方式也是一样的,可要不是ListView的话这种方式就不可用了。具体的就需要根据你实现的方式来调整了    /** 存放可见的ListView */    private List<Integer> visibleList = new ArrayList<Integer>();    /** 获取游戏Holder并且上报游戏曝光 */    private void gameInfoExposure() {        if (messageDetailMain == null || headViewHolder == null || headViewHolder instanceof ReplyHeaderStrategyView) {            return;        }        if (messageDetailMain.getContentType() != MsgContentType.MSG_CONTENT_TYPE_ARTICLE_CONTAIN_GAME) {            return;        }        ReplyActivityHeadViewHolder headHolder = (ReplyActivityHeadViewHolder) headViewHolder;        ListView listView = headHolder.getListView();        if (listView == null || listView.getVisibility() != View.VISIBLE) {            return;        }        int firstVisible = listView.getFirstVisiblePosition();        int lastVisible = listView.getLastVisiblePosition();        int index = listView.getHeaderViewsCount();        Map<String, RedGameBean> mapList = new HashMap<String, RedGameBean>();        // 需要上报的游戏Id集合        List<String> gameIds = new ArrayList<String>();        // 将最新可见item的index加入到临时list中        ArrayList<Integer> list = new ArrayList<Integer>();        // 标识是否提交游戏信息        boolean isSubmit = false;        int count = firstVisible > 0 ? firstVisible : 0;        // 遍历的时候下标要减一个,不然会有问题        for (int i = count; i <= lastVisible; i++) {            View tmp = listView.getChildAt((index + i) - firstVisible);            if (tmp != null) {                Object tag = tmp.getTag();                if (tag != null && tag instanceof RedGameHolder) {                    RedGameHolder holder = (RedGameHolder) tag;                    // 获取下载控件,并且判断是否可见                    View downloadView = holder.getDownloadView();                    //                    Rect scrollBounds = new Rect();                    downloadView.getHitRect(scrollBounds);                    // // 判断View是否移出去了不可见或者可见                    RedGameBean gameBean = holder.getGameBean();                    if (downloadView.getLocalVisibleRect(scrollBounds)) {                        // View 进入当前屏幕可视,哪怕一个像素                        list.add(i);                        mapList.put("" + i, gameBean);                    }                }            }        }        // 新可见item的index的集合        ArrayList<Integer> diffList = DataHelper.getDiffrent(list, visibleList);        if (!diffList.isEmpty()) {            for (Integer i : diffList) {                RedGameBean gameBean = mapList.get("" + i);                if (gameBean != null && !FileHelper.checkApkExist(mActivity, gameBean.getLocalApkName())) {                    String str = AppDefine.NA + ":" + gameBean.getId();                    gameIds.add(str);                    isSubmit = true;                }            }        }        // 更新list,将最新的可见item的index加入到list        visibleList.clear();        visibleList.addAll(list);        // 清空最新可见item的index的list        if (list != null) {            list.clear();        }        if (isSubmit) {            String ids = "";            if (gameIds.size() > 0) {                for (int i = 0; i < gameIds.size(); i++) {                    ids = ids + gameIds.get(i);                    if (i != gameIds.size() - 1)                        ids = ids + "|";                }                // 这里执行上报                gameIds.clear();            }            isSubmit = false;        }    }
0 0
原创粉丝点击