Android View的可见性检查之 getLocalVisibleRect与 getGlobalVisibleRect

getGlobalVisibleRect(rect);
是以屏幕左上角为参考系,
判断view有一部分在屏幕中,返回true(没有被父View遮挡)。
反之,如果它全部被父View遮挡住或者本身就是不可见的,返回false。

getLocalVisibleRect(rect);
当View可见时,以自身View左上角为参考系,坐标系的原点为View自己的坐标原点。
当View不可见时,以父控件左上角为参考系,坐标系的原点为View的父控件的坐标原点。

为了更好理解,Demo如下:(测试机分辨率为720*1440,橙红色view为400*400px。布局为一个RelativeLayout嵌套这TextView)

屏幕包含蓝色状态栏!!高度为55px,所以计算的结果要考虑到这个问题

当Textview设置marginLeft="100px"、marginTop="100px"时:

当Textview设置marginLeft="-100px"、marginTop="-100px"时:

当Textview设置marginRight="-100px"、marginBottom="-100px"时:

下面的理解主要针对getLocalVisibleRect(rect),View不可见的情况:

当Textview设置marginTop="-500px"时,此时TextView是在屏幕外的:

       

此时的getLocalVisibleRect(rect),坐标系的原点为它的父控件的坐标原点,也就是外面嵌套的RelativeLayout,RelativeLayout的宽高都是match_parent的,所以他的数值跟getGlobalVisibleRect(rect)是相同的。


当Textview设置layout_marginBottom="-500px",layout_marginRight="-500px",都在父布局的底部时,此时TextView是在屏幕外的:

高度要考虑底部虚拟导航栏!!高度为55px,所以计算的结果要考虑到这个问题

      

此时的getLocalVisibleRect(rect),坐标系的原点为它的父控件的坐标原点,也就是外面嵌套的RelativeLayout,RelativeLayout的宽高都是match_parent的,所以他的数值跟getGlobalVisibleRect(rect)是相同的。

TextView的宽、高为400px, layout_marginBottom="-500px",layout_marginRight="-500px",
所以TextView距离屏幕右间距为100px,距离屏幕下间距为100px,
考虑到下部虚拟导航栏高度为55px,所以TextView距离屏幕底部实际距离为(100px-55px)=45px

左面:720+100 =820px
上面:1440+45=1485px
右面:720+100+400 =1220px
下面:1440+45+400 =1885px

判断View1是否在某个View2可视区域内
当使用getLocalVisibleRect(rect)时,当View不在可视区域内时:
在顶部,Rect.top <0
在底部,Rect.bottom>View2.getHeight
所以
fun isCover(activity: Activity, view1: View, view2: View): Boolean {
        val rect = Rect()
        view1.getLocalVisibleRect(rect)
        return !(rect.top<0||rect.bottom>view2.height)
}

判断View可视区域占其自身百分比(当view1开始可视后调用,否则一直都是100%)
fun getVisibilePercent(activity: Activity, view1: View): Int {
        val rect = Rect()
        view1.getLocalVisibleRect(rect)
        Log.e("测试","rect.height ="+rect.height().toString() + " view1.height ="+view1.height)
       val a = rect.height() * 100 / view1.height
        Log.e("测试",a.toString())
        return a
}

...... 

判断View是否显示出现在屏幕上
fun isCoverScreen_LocalVisibleRect(view1: View): Boolean {
        val screenWidth = CFUtil.getScreenWidth()//获取屏幕宽度
        val screenHeight = CFUtil.getScreenHeight()//获取屏幕高度
        val rect = Rect()
        view1.getLocalVisibleRect(rect)
        return !(rect.top<0||rect.bottom>screenHeight)
}

总结

getGlobalVisibleRect(rect) 简单来说就是目标view在父view的映射,
然后从屏幕左上角开始计算,保存到 rect 中,注意是父view,而不是屏幕,因为demo的父view(RelativeLayout)和屏幕宽高是一样的。

getLocalVisibleRect(rect) 只要这个View的左上角在屏幕中,它的LocalVisibleRect的左上角坐标就一定是(0,0),
如果View的右下角在屏幕中,它的LocalVisibleRect右下角坐标就一定是(view.getWidth(), view.getHeight())。
如果不在屏幕中,他的Rect数值就跟getGlobalVisibleRect(rect)是一样的。

猜你喜欢

转载自blog.csdn.net/NewActivity/article/details/127498502