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

本文详细解析了`getGlobalVisibleRect`和`getLocalVisibleRect`方法在Android开发中的作用,通过实例演示了如何判断View的位置和可视范围,包括屏幕状态栏、布局偏移和视图覆盖情况。重点讲解了两者坐标系的区别以及在不同场景下的应用。

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)是一样的。

<think>我们正在讨论Android中的View.getGlobalVisibleRect(Rect)方法。根据用户的问题,他们想知道这个方法的作用。 根据引用[1]:这个方法用于获取View在屏幕中的位置,以判断View是否显示在屏幕中。 引用[2]和[3]提供了使用示例和区别说明。具体来说,引用[3]指出:getGlobalVisibleRect(Rect)返回的是View在屏幕坐标系中的可见区域(如果View被部分遮挡,则返回的是实际可见的矩形区域)。如果View完全可见,则返回的矩形就是View在屏幕上的位置;如果部分可见,则矩形会被裁剪为可见部分;如果完全不可见,则矩形可能为空(或者返回false)。 另外,引用[4]中有一个实际应用,在判断View是否在屏幕上可见时使用了getGlobalVisibleRect,并且结合其他条件(如可见区域的大小)来决定是否记录该View的显示次数。 因此,我们可以总结: getGlobalVisibleRect(Rect rect)方法的作用是:将View在屏幕坐标系(即相对于整个屏幕)中的可见区域(矩形)填充到传入的Rect对象中。如果View的任何部分可见,则返回true;如果完全不可见,则返回false(并且rect会被设置为空矩形)。 注意:屏幕坐标系的原点是屏幕的左上角,包括状态栏(status bar)在内。因此,返回的矩形的位置是相对于屏幕左上角的坐标。 下面我们详细解释: 1. 参数:我们需要传入一个Rect对象,方法会将View的可见部分(以矩形表示)的坐标设置到这个Rect对象中。 2. 返回值:如果View至少有一个像素可见,则返回true;否则返回false。 3. 坐标:矩形的位置是相对于屏幕左上角(包括状态栏)的绝对坐标。 使用示例: Rect rect = new Rect(); boolean isVisible = view.getGlobalVisibleRect(rect); if (isVisible) { // 此时rect中存储了View在屏幕上的可见区域 } else { // View不可见 } 注意:如果View本身是可见的(VISIBLE)并且没有被其他视图遮挡,那么返回的矩形就是整个View在屏幕上的位置。但是,如果View被父布局裁剪(例如在ScrollView中)或者被其他视图覆盖,那么返回的矩形就是实际可见的区域。 另外,引用[3]还提到getLocalVisibleRect的区别: getLocalVisibleRect返回的是View在其自身坐标系中的可见区域(相对于View自身左上角),而getGlobalVisibleRect返回的是相对于屏幕左上角的坐标。 因此,我们可以这样回答用户的问题: getGlobalVisibleRect(Rect)方法用于获取视图在屏幕坐标系中的可见区域(矩形),并将结果填充到传入的Rect对象中。它返回一个布尔值,表示视图是否至少有一部分可见。这个方法常用于判断视图是否在屏幕上可见,以及可见部分的具体位置和大小。 接下来,我们按照要求生成相关问题。</think>### Android View.getGlobalVisibleRect(Rect) 方法详解 `View.getGlobalVisibleRect(Rect)` 是 Android 中用于**检测视图在屏幕坐标系中的可见区域**的核心方法。它的作用是将当前 View 在屏幕上的可见部分(矩形区域)的坐标信息填充到传入的 Rect 对象中。以下是具体说明: #### 核心功能 1. **坐标系** 返回的坐标是**相对于屏幕左上角**的绝对坐标(包括状态栏区域),坐标原点 (0,0) 是屏幕左上角[^3]。 2. **可见性判断** - 若 View 完全可见 → 返回的 Rect 等于 View 在屏幕上的完整边界 - 若 View 部分被遮挡(如被状态栏、键盘或其它 View 覆盖)→ 返回实际可见部分的矩形 - 若 View 完全不可见 → 返回 `false` 且 Rect 被置为空(或返回 (0,0,0,0)) 3. **返回值** `boolean` 类型: - `true`:View 至少有一个像素可见 - `false`:View 完全不可见[^1][^4] #### 典型使用场景 ```java Rect visibleRect = new Rect(); boolean isVisible = myView.getGlobalVisibleRect(visibleRect); if (isVisible) { // 获取可见区域的坐标 int visibleLeft = visibleRect.left; // 可见区域左边界X坐标 int visibleTop = visibleRect.top; // 可见区域上边界Y坐标(含状态栏高度) int visibleWidth = visibleRect.width(); int visibleHeight = visibleRect.height(); } else { // View完全不可见 } ``` #### 其他方法的区别 | 方法 | 坐标系 | 特点 | |-----------------------|--------------------|-----------------------------| | `getGlobalVisibleRect` | 屏幕绝对坐标 | 包含状态栏高度[^3] | | `getLocalVisibleRect` | View自身坐标系 | 左上角始终为(0,0) | | `getHitRect` | 父容器坐标系 | 不考虑遮挡 | | `getDrawingRect` | 父容器坐标系 | 包含滚动偏移 | #### 注意事项 1. **状态栏高度影响** 返回的 `top` 值包含状态栏高度(例如:若状态栏高50px,View距屏幕顶20px,则 `top=70px`)[^3] 2. **性能优化建议** 在滚动容器(如RecyclerView)中频繁调用可能影响性能,建议结合`ViewTreeObserver.OnScrollChangedListener` 使用 3. **可见性综合判断** 需同时检查 `View.isShown()` 和 `getVisibility() == View.VISIBLE` 确保逻辑严谨[^4] > 示例:检测View是否至少一半可见 > ```java > if (view.getGlobalVisibleRect(rect)) { > int visibleHeight = rect.height(); > int totalHeight = view.getHeight(); > if (visibleHeight > totalHeight / 2) { > // 超过50%面积可见 > } > } > ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值