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

    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)]

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值