这篇文章主要介绍如何判断 view在屏幕中已经展现,主要可用于打点,视频播放等
前段时间,PM提出一个打点需求.要求当某个模块/view 在用户可见的时候 打点,否则不打. 之前的打点都是在服务端数据返回,view被加载的时候就已经打上了,但是很多时候,这些模块view只是被实例化了,并没有真的被用户看到.尤其是在 listview 或 recyclerview 的header里面 .
其实觉得这个需求很扯淡.但是确实很重要,毕竟精准的数据关系到 产品的走向.
刚开始想用view的一些API方法来实现.如:onWindowFocusChanged onWindowVisibilityChanged 等等,但遗憾的是,这些方法都达不到要求. 比如在listview/recyclerview的header里面,在 header被加载出来时,header里面的全部view都已经被实例化.
刚开始比较急,第一个想到的是算高度,根据某个view的高度,父布局滑动的高度,来计算是否在屏幕内, 但是这样会产生大量"恶心"代码,而且一旦这个"真实展现"要给大量view打的话, 非常非常多的计算代码都会出来.
后来看到一些视频软件,比如 QQ看点,迅雷App .一个视频列表,滑动到一个视频的时候,就自动播放,上一个视频就暂停.灵感就来了,它一定是监测到了这个视频view 被滑到了屏幕中间, 或者比上一个视频view 显示的区域大.
那么就找到了 getLocalVisibleRect(Rect r) 没错,就是这个问题的主角了. 进去看下 它调用的是
public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
int width = mRight - mLeft;
int height = mBottom - mTop;
if (width > 0 && height > 0) {
r.set(0, 0, width, height);
if (globalOffset != null) {
globalOffset.set(-mScrollX, -mScrollY);
}
return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
}
return false;
}
可以看到,这个方法如果返回true.则证明view可见,并且rect对象就是这个view的可见部分.
直接贴出判断方法.
private boolean isVisible(View v) {
return v.getLocalVisibleRect(new Rect());
}
这样来看是不是就简单多了呢.至此,这个问题的主要解决方法就完成了.
但是 我们对每一个view都这么判断着实麻烦.下面也贴出封装的真实展现的监听类吧.
public class BaseRealVisibleUtil imple