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了,才能get
ItemData 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进去的
![image.png](https://upload-images.jianshu.io/upload_images/6273713-ecb38f70ac000bf6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
到这里我们就实现了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 {
//刚进入列表时统计当前屏幕可见views
private boolean isFirstVisible = true;
//用于统计曝光量的map
private 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() {
@Override
public 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);
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//刚进入列表时统计当前屏幕可见views
if (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-catch
try {
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了,才能get
ItemData 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;
}
写在最后
很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从哪里入手去学习,对此我整理了一些资料
如果你熟练掌握以下列出的知识点,相信将会大大增加你通过前两轮技术面试的几率!这些内容都供大家参考,互相学习。
①「Android面试真题解析大全」PDF完整高清版+②「Android面试知识体系」学习思维导图压缩包,最后觉得有帮助、有需要的朋友可以点个赞
indLastVisibleItemPosition();
return range;
}
写在最后
很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从哪里入手去学习,对此我整理了一些资料
如果你熟练掌握以下列出的知识点,相信将会大大增加你通过前两轮技术面试的几率!这些内容都供大家参考,互相学习。
①「Android面试真题解析大全」PDF完整高清版+②「Android面试知识体系」学习思维导图压缩包,最后觉得有帮助、有需要的朋友可以点个赞
[外链图片转存中…(img-GPrZq5Od-1719210197354)]
[外链图片转存中…(img-VIackrS1-1719210197355)]
[外链图片转存中…(img-wE6jawuV-1719210197355)]