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(); } }}
上面的代码是在百度知道里面找的。思路也是跟一样。其实这块并不难,难点在于查找数据方面。因为我有多个界面需要统计,所以每个界面处理都不一样,但思路是一样的。
因为首页有两种条目需要上报的,所以处理也是需要结合两种条目的处理方式一起处理。
下面这个是取出两个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; } }
下面的代码就是自己备忘的了,有需要的同鞋也可以参照着改哈。思路完全是跟上面的一样,只不过界面不一样了而已
/** 存放可见的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
- Android ListView获取当前可视区域条目数据
- Android的LisTView 条目过多,最后一条在可视范围
- Android获取窗口可视区域大小: getWindowVisibleDisplayFrame()
- Android获取窗口可视区域大小: getWindowVisibleDisplayFrame()
- JS获取当前手机浏览器可视区域大小
- Android的ListView数据更新后,如何使最新的条目可以自动滚动到可视范围内?
- Android的ListView数据更新后,如何使最新的条目可以自动滚动到可视范围内?
- Android的ListView数据更新后,如何使最新的条目可以自动滚动到可视范围内
- Android的ListView数据更新后,如何使最新的条目可以自动滚动到可视范围内?
- android listview 如何动态获取当前页面的头条目的item
- 我的Android进阶之旅------>Android的ListView数据更新后,如何使最新的条目可以自动滚动到可视范围内?
- 我的Android进阶之旅------>Android的ListView数据更新后,如何使最新的条目可以自动滚动到可视范...
- Android--------ListView多条目展示数据
- 获取RecyclerView的可视条目索引
- Android 获取listview中Item的可视百分比
- 解决Cocos2d-x 3.0 以后 ListView、PageView Android下可视区域绿问题
- JS获取浏览器可视区域尺寸
- JS获取浏览器可视区域尺寸
- shiyan1连接oracle数据库试验
- MySQLWorkbench 双击无反应
- 一个App完成入门篇(三)-完善主框架 企
- 在Android应用中读取彩信文件
- Windows 和Linux利用tftp协议传送文件
- Android ListView获取当前可视区域条目数据
- test1000
- 《python计算机视觉编程》读书笔记------5(Numpy篇)
- C++构造函数和拷贝构造函数等的使用
- Linux 字符串整数比较大小,-w,-d,-L等命令,
- 网易公开课 斯坦福大学公开课:机器学习课程 notes2
- PHP 魔术变量
- servJump extends HttpServlet //request.getRequestDispatcher //response.sendRedirect("http
- :link,:visited,:focus,:hover,:active详解