Android:View的getLocalVisibleRect()和getGlobalVisibleRect()的区别

代码片段:

 ImageView rectImage = findViewById(R.id.rect_image);
 rectImage.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
     
            @Override
            public void onGlobalLayout() {
     
                Rect localRect = new Rect();
                //getLocalVisibleRect相对于View本身左上角进行计算
                rectImage.getLocalVisibleRect(localRect);
                Log.i("lyyyyyyyyy", "getLocalVisibleRect: "+localRect.toString());

                //getGlobalVisibleRect相对于整个屏幕坐标系进行计算
                rectImage.getGlobalVisibleRect(localRect);
                Log.i("lyyyyyyyyy", "getGlobalVisibleRect: "+localRect.toString());
            }
        });
// 打印结果:
2021-02-19 17:37:57.658 17409-17409/com.example.myapplication4 I/lyyyyyyyyy: getLocalVisibleRect: Rect(0, 0 - 165, 330)
2021-02-19 17:37:57.659 17409-17409/com.example.myapplication4 I/lyyyyyyyyy: getGlobalVisibleRect: Rect(458, 121 - 623, 451)
2021-02-19 17:37:57.671 17409-17409/com.example.myapplication4 I/lyyyyyyyyy: getLocalVisibleRect: Rect(0, 0 - 165, 330)
2021-02-19 17:37:57.671 17409-17409/com.example.myapplication4 I/lyyyyyyyyy: getGlobalVisibleRect: Rect(458, 121 - 623, 451)
2021-02-19 17:37:58.639 17409-17409/com.example.myapplication4 I/lyyyyyyyyy: getLocalVisibleRect: Rect(0, 0 - 165, 330)
2021-02-19 17:37:58.639 17409-17409/com.example.myapplication4 I/lyyyyyyyyy: getGlobalVisibleRect: Rect(458, 121 - 623, 451)

GlobalLayoutListener:布局的状态发生变化或者可见性发生变化才会调用。准确的说,这个不是监听View的加载完成,而是监听布局变化的。

所以会调用多次,使用的时候需要注意。

解决的办法就是第一次回调后,就把回调remove掉,如:rectImage.getViewTreeObserver().removeOnGlobalLayoutListener(this);

测试不同情况下OnGlobalLayoutListener的调用次数:
1.启动后调用了三次onGlobalLayout。
2.屏幕锁屏会调用两次。
3.退出app重进调用一次。
4.屏幕锁屏后重新打开会调用两次(小米两次),其中一次猜测是控件的可见性改变了。
5.改变可见性和修改控件大小,修改layoutgravity一样都会各自调用一次。

回到正题:
很明显调用getLocalVisibleRect(Rect r)后localRect变量中的right和bottom正是图片的长和宽。

而调用getGlobalVisibleRect(Rect r)后localRect变量中的top是ActionBar的高度+View的上边距,bottom是top+View的高;left则为View的左边距,right为left+View的宽。(Android获取ActionBar高度链接)

所以目前的结论是:getLocalVisibleRect(Rect r)方法可以把View的长和宽映射到一个Rect对象上,映射的参照物就是View本身左上角的坐标系。
而getGlobalVisibleRect(Rect r)方法可以把View在整个屏幕中的偏移量映射到一个Rect对象上,映射的参照物是屏幕左上角的坐标系。

上面的情况是View没有超出屏幕区域的数据,那么超出屏幕区域再次进行测试会发现1.getGlobalVisibleRect()方法的作用是获取视图在屏幕坐标中的可视区域。只要该视图没有被遮挡rectImage.getLocalVisibleRect()的坐标总是等于:(0, 0, rectImage.getwidth(), rectImage.getheight()),而遮挡后的left和top则为以View本身左上角进行计算的偏移量,所以getLocalVisibleRect的作用是获取视图本身可见的坐标区域,坐标以自己的左上角为原点(0,0)

测试图:

你可能感兴趣的:(Android)