代码片段:
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)
测试图: