近期pm提出需要统计首页商品的曝光亮,由于我们的首页是用的recylerview实现的,这里就来讲下如何使用监听recylerview的滚动事件来实现子view的曝光量统计,我们这里说的view都是列表中的子item条目(子view)

先来看下统计结果图

左边是我们的列表,右边是我们统计到每个条目的曝光量。下面就来讲讲具体实现步骤。

一,activity中使用recylerview并显示数据

这里我不再啰嗦,recylerview最基础的使用。

二,监听recylerview的滚动事件OnScrollListener

onScrollStateChanged:监听滚动状态 onScrolled:监听滚动 我们接下来的统计工作,就是拿这两个方法做文章。

//检测recylerview的滚动事件recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {@Overridepublic void onScrollStateChanged(RecyclerView recyclerView, int newState) {/*我这里通过的是停止滚动后屏幕上可见view。如果滚动过程中的可见view也要统计,你可以根据newState去做区分SCROLL_STATE_IDLE:停止滚动SCROLL_STATE_DRAGGING: 用户慢慢拖动SCROLL_STATE_SETTLING:惯性滚动*/if (newState == RecyclerView.SCROLL_STATE_IDLE) {.....}}@Overridepublic void onScrolled(RecyclerView recyclerView, int dx, int dy) {super.onScrolled(recyclerView, dx, dy);........}});
复制代码

首先再次明确下,我们要统计的是用户停止滑动时,显示在屏幕的上控件。所以我们要监测到onScrollStateChanged 方法中 newState == RecyclerView.SCROLL_STATE_IDLE 时,也就是用户停止滚动。然后在这里做文章。

三,获取屏幕内可见条目的起始位置

这里的起始位置就是指我们屏幕当中最上面和最下面条目的位置。比如下图的0就是最上面的可见条目,3就是最下面的可见条目。我们次数的曝光view就是0,1,2,3 这个时候这四个条目显示在屏幕中。我们这时就要对这4个view的曝光量进行加1

那么接下来的重点就是要去获取屏幕内可见条目的起始位置。获取到起始位置后,当前屏幕里的可见条目就都能拿到了。 而recylerview的manager正好给我们提供的有对应的方法。 findFirstVisibleItemPosition()和findLastVisibleItemPosition() 看字面意思就能知道这时干嘛用的。 但是我们的manager不止LinearLayoutManager一种,所以我们要做下区分,

//这里我们用一个数组来记录起始位置
int[] range = new int[2];
RecyclerView.LayoutManager manager = reView.getLayoutManager();
if (manager instanceof LinearLayoutManager) {range = findRangeLinear((LinearLayoutManager) manager);
} else if (manager instanceof GridLayoutManager) {range = findRangeGrid((GridLayoutManager) manager);
} else if (manager instanceof StaggeredGridLayoutManager) {range = findRangeStaggeredGrid((StaggeredGridLayoutManager) manager);
}
复制代码

LinearLayoutManager和GridLayoutManager获取起始位置方法如下

private int[] findRangeLinear(LinearLayoutManager manager) {int[] range = new int[2];range[0] = manager.findFirstVisibleItemPosition();range[1] = manager.findLastVisibleItemPosition();return range;
}
private int[] findRangeGrid(GridLayoutManager manager) {int[] range = new int[2];range[0] = manager.findFirstVisibleItemPosition();range[1] = manager.findLastVisibleItemPosition();return range;
}
复制代码

StaggeredGridLayoutManager获取起始位置有点复杂,如下

private int[] findRangeStaggeredGrid(StaggeredGridLayoutManager manager) {int[] startPos = new int[manager.getSpanCount()];int[] endPos = new int[manager.getSpanCount()];manager.findFirstVisibleItemPositions(startPos);manager.findLastVisibleItemPositions(endPos);int[] range = findRange(startPos, endPos);return range;}private int[] findRange(int[] startPos, int[] endPos) {int start = startPos[0];int end = endPos[0];for (int i = 1; i < startPos.length; i++) {if (start > startPos[i]) {start = startPos[i];}}for (int i = 1; i < endPos.length; i++) {if (end < endPos[i]) {end = endPos[i];}}int[] res = new int[]{start, end};return res;}
复制代码

四,获取到起始位置以后,我们就根据位置获取到view及view中的数据

上面第三步拿到屏幕内可见条目的起始位置以后,我们就用一个for循环,获取当前屏幕内可见的所有子view

for (int i = range[0]; i <= range[1]; i++) {View view = manager.findViewByPosition(i);recordViewCount(view);
}
复制代码

recordViewCount是我自己写的用于获取子view内绑定数据的方法

//获取view绑定的数据
private void recordViewCount(View view) {if (view == null || view.getVisibility() != View.VISIBLE ||!view.isShown() || !view.getGlobalVisibleRect(new Rect())) {return;}int top = view.getTop();int halfHeight = view.getHeight() / 2;int screenHeight = UiUtils.getScreenHeight((Activity) view.getContext());int statusBarHeight = UiUtils.getStatusBarHeight(view.getContext());if (top < 0 && Math.abs(top) > halfHeight) {return;}if (top > screenHeight - halfHeight - statusBarHeight) {return;}//这里获取的是我们view绑定的数据,相应的你要去在你的view里setTag,只有set了,才能getItemData tag = (ItemData) view.getTag();String key = tag.toString();if (TextUtils.isEmpty(key)) {return;}hashMap.put(key, !hashMap.containsKey(key) ? 1 : (hashMap.get(key) + 1));Log.i("qcl0402", key + "----出现次数:" + hashMap.get(key));
}
复制代码

这里有几点需要注意

  • 1,这这里起始位置的view显示区域如果不超过50%,就不算这个view可见,进而也就不统计曝光。
  • 2,我们通过view.getTag();获取view里的数据,必须在此之前setTag()数据,我这里setTag是在viewholder中把数据set进去的

到这里我们就实现了recylerview列表中view控件曝光量的统计了。下面贴出来完整的代码给大家

package com.example.qcl.demo.xuexi.baoguang;import android.app.Activity;
import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;import com.example.qcl.demo.utils.UiUtils;import java.util.concurrent.ConcurrentHashMap;/*** 2019/4/2 13:31* author: qcl* desc: 安卓曝光量统计工具类* wechat:2501902696*/
public class ViewShowCountUtils {//刚进入列表时统计当前屏幕可见viewsprivate boolean isFirstVisible = true;//用于统计曝光量的mapprivate ConcurrentHashMap<String, Integer> hashMap = new ConcurrentHashMap<String, Integer>();/** 统计RecyclerView里当前屏幕可见子view的曝光量** */void recordViewShowCount(RecyclerView recyclerView) {hashMap.clear();if (recyclerView == null || recyclerView.getVisibility() != View.VISIBLE) {return;}//检测recylerview的滚动事件recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {@Overridepublic void onScrollStateChanged(RecyclerView recyclerView, int newState) {/*我这里通过的是停止滚动后屏幕上可见view。如果滚动过程中的可见view也要统计,你可以根据newState去做区分SCROLL_STATE_IDLE:停止滚动SCROLL_STATE_DRAGGING: 用户慢慢拖动SCROLL_STATE_SETTLING:惯性滚动*/if (newState == RecyclerView.SCROLL_STATE_IDLE) {getVisibleViews(recyclerView);}}@Overridepublic void onScrolled(RecyclerView recyclerView, int dx, int dy) {super.onScrolled(recyclerView, dx, dy);//刚进入列表时统计当前屏幕可见viewsif (isFirstVisible) {getVisibleViews(recyclerView);isFirstVisible = false;}}});}/** 获取当前屏幕上可见的view* */private void getVisibleViews(RecyclerView reView) {if (reView == null || reView.getVisibility() != View.VISIBLE ||!reView.isShown() || !reView.getGlobalVisibleRect(new Rect())) {return;}//保险起见,为了不让统计影响正常业务,这里做下try-catchtry {int[] range = new int[2];RecyclerView.LayoutManager manager = reView.getLayoutManager();if (manager instanceof LinearLayoutManager) {range = findRangeLinear((LinearLayoutManager) manager);} else if (manager instanceof GridLayoutManager) {range = findRangeGrid((GridLayoutManager) manager);} else if (manager instanceof StaggeredGridLayoutManager) {range = findRangeStaggeredGrid((StaggeredGridLayoutManager) manager);}if (range == null || range.length < 2) {return;}Log.i("qcl0402", "屏幕内可见条目的起始位置:" + range[0] + "---" + range[1]);for (int i = range[0]; i <= range[1]; i++) {View view = manager.findViewByPosition(i);recordViewCount(view);}} catch (Exception e) {e.printStackTrace();}}//获取view绑定的数据private void recordViewCount(View view) {if (view == null || view.getVisibility() != View.VISIBLE ||!view.isShown() || !view.getGlobalVisibleRect(new Rect())) {return;}int top = view.getTop();int halfHeight = view.getHeight() / 2;int screenHeight = UiUtils.getScreenHeight((Activity) view.getContext());int statusBarHeight = UiUtils.getStatusBarHeight(view.getContext());if (top < 0 && Math.abs(top) > halfHeight) {return;}if (top > screenHeight - halfHeight - statusBarHeight) {return;}//这里获取的是我们view绑定的数据,相应的你要去在你的view里setTag,只有set了,才能getItemData tag = (ItemData) view.getTag();String key = tag.toString();if (TextUtils.isEmpty(key)) {return;}hashMap.put(key, !hashMap.containsKey(key) ? 1 : (hashMap.get(key) + 1));Log.i("qcl0402", key + "----出现次数:" + hashMap.get(key));}private int[] findRangeLinear(LinearLayoutManager manager) {int[] range = new int[2];range[0] = manager.findFirstVisibleItemPosition();range[1] = manager.findLastVisibleItemPosition();return range;}private int[] findRangeGrid(GridLayoutManager manager) {int[] range = new int[2];range[0] = manager.findFirstVisibleItemPosition();range[1] = manager.findLastVisibleItemPosition();return range;}private int[] findRangeStaggeredGrid(StaggeredGridLayoutManager manager) {int[] startPos = new int[manager.getSpanCount()];int[] endPos = new int[manager.getSpanCount()];manager.findFirstVisibleItemPositions(startPos);manager.findLastVisibleItemPositions(endPos);int[] range = findRange(startPos, endPos);return range;}private int[] findRange(int[] startPos, int[] endPos) {int start = startPos[0];int end = endPos[0];for (int i = 1; i < startPos.length; i++) {if (start > startPos[i]) {start = startPos[i];}}for (int i = 1; i < endPos.length; i++) {if (end < endPos[i]) {end = endPos[i];}}int[] res = new int[]{start, end};return res;}}
复制代码

使用就是在我们的recylerview设置完数据以后,把recylerview传递进去就可以了。如下图:

我们统计到曝光量,拿到曝光view绑定的数据,就可以结合后面的view点击,来看下那些商品view的曝光量高,那些商品的转化率高。当然,这都是运营小伙伴的事了,我们只需要负责把曝光量统计到即可。 如果你有任何编程方面的问题,可以加我微信交流 2501902696(备注编程)

by:年糕妈妈qcl

转载于:https://juejin.im/post/5ca30ad1e51d4514c01634f1

Android 曝光采集(商品view曝光量的统计)相关推荐

  1. Android 曝光采集,商品view曝光量的统计,判断RecyclerView中某子view是否可见 view是否显示在屏幕中 view展示次数统计...

    近期pm提出需要统计首页商品的曝光亮,由于我们的首页是用的recylerview实现的,这里就来讲下如何使用监听recylerview的滚动事件来实现子view的曝光量统计,我们这里说的view都是列 ...

  2. Android 曝光采集:以商品 view 曝光量的统计为例

    本文由神策数据的标杆客户年糕妈妈的技术团队创作. 全文将为你介绍安卓端有效曝光统计的五步骤: 要确定什么样的算有效曝光(例:在屏幕停留时间超过一个值如 2 秒) 监听到每个 view 移入和移出屏幕的 ...

  3. android view 曝光,Android 曝光采集(商品view曝光量的统计)第二弹

    安卓端有效曝光统计步骤 1 ,要确定什么样的算有效曝光(在屏幕停留时间超过一个值如2秒) 2,监听到每个view移入和移出屏幕的事件 3,把数据绑定到view(view相当于数据的载体) 4,根据监听 ...

  4. Android RecyclerView曝光采集

    一.背景 近期pm提出需要统计首页商品的曝光亮,由于我们的首页是用的recylerview实现的,这里就来讲下如何使用监听recylerview的滚动事件来实现子view的曝光量统计,我们这里说的vi ...

  5. 弘辽科技:拼多多不交保证金商品有曝光量吗?怎么提升曝光?

    电商行业对人们生活带来的影响是非常大的,现在,几乎所有会上网的人都有过在网上购物的精力.特别是拼多多这个受众群体非常大的平台,那么拼多多不交保证金商品有曝光量吗? 拼多多不交保证金商品有曝光量吗? 拼 ...

  6. 【流媒體】Android 实时视频采集—Camera预览采集

    [流媒體]Android 实时视频采集-Cameara预览采集 SkySeraph Mar 26th 2012  SZ Email:skyseraph00@163.com 更多精彩请直接访问SkySe ...

  7. android 多数据图表,Android统计图表MPAndroidChart:为多条统计折线动态更新数据,以高温低温曲线为例【7】...

     Android统计图表MPAndroidChart:为多条统计折线动态更新数据,以高温低温曲线为例[7] 本文在附录文章6的基础上,为Android统计图表MPAndroidChart的同一个L ...

  8. Android 手机采集摄像头视频 socket 视频传输实时传播

    这里搜集了两种实现Android 手机采集摄像头视频 socket 视频传输实时传播的方法,两种都可以使用. 第一种如下: 1.通过客户端socket请求,服务端接受到请求后,获取socket的输出流 ...

  9. Android 中 简单商品列表 的运用

     可参考Android 中对 ListView 中 进行增删改查 完成效果如图所示: GoodActivity package com.example.sqlitedemo;import androi ...

最新文章

  1. iphone XCode调试技巧之EXC_BAD_ACCESS中BUG解决
  2. 实时滚动图表绘制方法: LightningChart教程 + 源码下载
  3. ice mac 安装
  4. java表格树_Java程序员值得拥有的TreeMap指南
  5. 链表之删除单链表倒数第K个节点
  6. pq 中m函数判断嵌套_压轴题的热点,二次函数与几何的结合,谁会谁吃香
  7. 纯CSS自定义button按钮的点击特效
  8. 今晚直播丨Oracle数据库之Object的Access方法和结合方法
  9. 吴恩达|机器学习作业6.0支持向量机(SVM)
  10. 机器学习和传统编程有什么区别?✅
  11. [工具] IntelliJ IDEA 中文语言包插件
  12. pgadmin4使用教程
  13. 自己动手写CPU(6)简单算术操作指令
  14. XLua官方Examples 08_Hotfix 热补丁的示例【2】
  15. numpy.arctan, math.atan, math.atan2的区别
  16. Groovy脚本极限优化
  17. 分析了全国 3447 个地铁站后发现的秘密
  18. 粒子群算法python(含例程代码与详解)
  19. 经销商网上订货系统流程小计,供货商订单下单软件
  20. Spring Cloud OAuth2 认证服务器

热门文章

  1. 苹果手机测试网络速度的软件,iPhone6怎么看网速?查看苹果6 Plus网速给不给力的方法...
  2. caffe特殊层:permute\reshape\flatten\slice\concat
  3. C++高级搜索算法迭代加深—————骑士精神
  4. 什么是安全沙箱技术?如何评估应用程序安全性?
  5. 网络营销高人的8大生意经:病毒性营销
  6. 文件已上传服务器去哪找,ftp文件服务器上传后的文件在哪
  7. 有一种遥远,叫从家到公司的距离
  8. C++中的struct
  9. 小敏利用计算机设计了一个计算程序,七年级上期中练习卷2013-2014第一学期定稿(10页)-原创力文档...
  10. 冷战 (并查集按秩归并)