getDrawingRect,getHitRect,getLocalVisibleRect,getGlobalVisibleRect
本文主要大体讲下getHitRect()、getDrawingRect()、getLocalVisibleRect()、getGlobalVisibleRect、
getLocationOnScreen、getLocationWindow方法的作用。
getHitRect()
android sdk文档中给出的解释是:Hit rectangle in parent's coordinates.看字面的意思应该是将矩形映射为父视图中的坐标,看起来还不是非常的清楚,下面就拿一个具体的示例来说明。
代码样式如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="450px"
android:layout_height="450px"
android:orientation="vertical"
android:layout_gravity="center_horizontal"
android:background="@android:color/holo_red_light">
<TextView
android:layout_width="200px"
android:layout_height="200px"
android:layout_marginTop="100px"
android:layout_gravity="center_horizontal"
android:text="测试区域"
android:gravity="center"
android:textStyle="bold"
android:background="@android:color/holo_blue_bright"/>
</LinearLayout>
public class MainActivity extends Activity {
private View testView;
private final static String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testView = findViewById(R.id.testView);
testView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
testView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
Rect rect = new Rect();
testView.getHitRect(rect);
Log.i(TAG, "--left: " + rect.left + "--top: " + rect.top + "--right: " + rect.right + "--bottom: " + rect.bottom);
}
});
}
在模拟器显示样式如下:

打印的结果:
07-27 16:03:00.017 9540-9540/? I/MainActivity﹕ --left: 125--top: 100--right: 325--bottom: 300
getDrawingRect()
下面测试getDrawingRect()方法,先看布局文件如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="400px"
android:layout_height="400px"
android:layout_gravity="center"
android:background="@android:color/holo_blue_dark"
android:orientation="vertical">
<TextView
android:id="@+id/test"
android:layout_width="200px"
android:layout_height="200px"
android:layout_gravity="center_horizontal"
android:layout_marginTop="150px"
android:background="@android:color/holo_red_light"
android:gravity="center"
android:text="测试区域" />
</LinearLayout>
**测试代码如下**
public class MainActivity extends Activity {
private final static String TAG = "MainActivity";
private View testView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testView = findViewById(R.id.test);
testView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
testView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
Rect rect = new Rect();
testView.getDrawingRect(rect);
Log.i(TAG, ">>>>>>>>>>>>>>>>rect.left: " + rect.left + "---rect.top: " + rect.top + "---rect.right: " + rect.right + "---rect.bottom: " + rect.bottom);
}
});
}
}

运行后结果如下:
I/MainActivity﹕ >>>>>>>>>>>>>>>>rect.left: 0---rect.top: 0---rect.right: 200---rect.bottom: 200
下面看下源码中的实现,源码实现如下:
public void getDrawingRect(Rect outRect) {
outRect.left = mScrollX;
outRect.top = mScrollY;
outRect.right = mScrollX + (mRight - mLeft);
outRect.bottom = mScrollY + (mBottom - mTop);
}
从代码实现我们可以看出:
1.getDrawingRect方法,是以view自身作为坐标系的,上例中rect.left与rect.top的值是均为0,因为测试的view均未发生滚动。
2.如果view自身发生了滚动,那么getDrawingRect(Rect outRect)中outRect存储了view滚动后到原始的坐标系的位置。
getLocalVisibleRect()与getGlobalVisibalRect的区别
以下摘自:http://cxyclub.cn/n/76738/
作为测试的目的,我写了这样一个布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/container"
tools:context=".MainActivity"
android:paddingLeft="10px">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/innerL"
android:paddingLeft="20px">
<ImageView
android:id="@+id/expandedImage"
android:layout_width="wrap_content"
android:src="@drawable/thumb1"
android:layout_height="wrap_content"/>
</LinearLayout>
</RelativeLayout>
另外为了方便测试,我将虚拟机设置为1dp=1px,大小等于320x480,因为这两个方法在View对象里面,所以基本上继承自View的对象都可以使用,也是为了方便自己,我使用ImageView作为测试对象,图片大小为160x120px。
下面是我自己的一个测试过程:
因为getLocalVisibleRect只有一个参数,所以我从这个方法入手代码如下:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView imageView = (ImageView) findViewById(R.id.expandedImage);
imageView.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Rect localRect = new Rect();
imageView.getLocalVisibleRect(localRect);
System.out.println("local" + localRect);
}
});
}
程序执行后Logcat输出:
localRect(0, 0 ,160, 120)
很明显localRect变量中的right和bottom正是图片的长和宽。
目前的结论是:getLocalVisibleRect(Rect r)方法可以把视图的长和宽映射到一个Rect对象上。
这里我们先放下这个方法,把注意力集中到getGlobalVisibleRect方法中。
将代码改为:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView imageView = (ImageView) findViewById(R.id.expandedImage);
imageView.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Rect globalRect = new Rect();
imageView.getGlobalVisibleRect(globalRect);
System.out.println("global" + globalRect);
}
});
}
Logcat输出:
globalRect(30, 81,190, 201)
除了30和190可以猜测出是什么(即left和right),其他的基本上没有什么线索,只知道是top和bottom。30是paddingLeft,即图片向右偏移了30px,因此right很自然就多了30px
top和bottom要知道是什么,我用了最笨的办法,就是用尺子量。

可见,这81像素就是状态栏加上ActionBar的高度,所以Bottom120加上81就是201
目前的结论是:getGlobalVisibleRect方法的作用是获取视图在屏幕坐标系中的偏移量。
那么,我的结论真的是正确的吗,其实我也不知道,继续测试下去。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/container"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="320dp"
android:layout_height="480dp"
android:orientation="vertical"
android:id="@+id/innerL"
android:background="#550000ff"
android:layout_marginLeft="-50px"
android:layout_marginTop="30px">
</LinearLayout>
</RelativeLayout>
布局效果如下:这种布局的目的是让这个View超出屏幕区域

java代码如下:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final LinearLayout ll = (LinearLayout) findViewById(R.id.innerL);
ll.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Rect localRect = new Rect();
ll.getLocalVisibleRect(localRect);
Rect globalRect = new Rect();
ll.getGlobalVisibleRect(globalRect);
System.out.println("global" + globalRect);
System.out.println("local" + localRect);
}
});
}
Logcat数据:
`globalRect(0, 111 - 271, 480) localRect(49, 0 - 320, 369)`
先来画图分析globalRect中的数据,在前面我们知道globalRect是基于屏幕坐标系的

从上图可以看出,蓝色区域的四个点的坐标实际上是LinearLayout在屏幕坐标系的可见区域。
**结论:**
***getGlobalVisibleRect方法的作用是获取视图在屏幕坐标中的可视区域***
另外需要说的是,getGlobalVisibleRect还可以接受第二个Point类型的参数:
`targetView.getGlobalVisibleRect(Rect r, Point gobalOffset)`
调用完毕后,globalOffset的值就是targetView原点偏离屏幕坐标原点的距离。
现在来看localRect(49, 0 - 320, 369),初步猜测它是基于视图本身的坐标,**只要该视图没有被遮挡,targetView.getLocalVisibleRect()的坐标总是等于:
(0, 0, targetView.getwidth(), targetView.getheight())**。
从布局不难看出,我们让它向左偏移了50个像素,因此它本身的坐标也跟着向左移动50像素,
至于为什么是49,这个我也不太清楚。因为视图的top和right在该布局中总是可见,所以是0和320,而bottom已经超出了屏幕, 所以480(屏幕的高度)-111(ActionBar+statusBar+marginTop)=369.
**结论:**
`getLocalVisibleRect的作用是获取视图本身可见的坐标区域,坐标以自己的左上角为原点(0,0)`
最后测试图:

布局文件代码:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/container"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/innerL">
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/thumb1"/>
</LinearLayout>
<TextView
android:id="@+id/local"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"/>
<TextView
android:id="@+id/global"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/local"
android:layout_below="@id/local"/>
<TextView
android:id="@+id/offset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/local"
android:layout_below="@id/global"/>
</RelativeLayout>
程序逻辑:
package com.whathecode.zoomimage;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity
{
private int lastX = 0;
private int lastY = 0;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView imageView = (ImageView) findViewById(R.id.img);
imageView.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int dx = (int) event.getRawX() - lastX;
int dy = (int) event.getRawY() - lastY;
int left = v.getLeft() + dx;
int top = v.getTop() + dy;
int right = v.getRight() + dx;
int bottom = v.getBottom() + dy;
v.layout(left, top, right, bottom);
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
Rect localRect = new Rect();
v.getLocalVisibleRect(localRect);
((TextView) findViewById(R.id.local))
.setText("local" + localRect.toString());
Rect globalRect = new Rect();
Point globalOffset = new Point();
v.getGlobalVisibleRect(globalRect, globalOffset);
((TextView) findViewById(R.id.global))
.setText("global" + globalRect.toString());
((TextView) findViewById(R.id.offset))
.setText("globalOffset:" + globalOffset.x + "," + globalOffset.y);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
});
}
}
getLocationOnScreen()
getLocationWindow()
getDrawingRect,getHitRect,getLocalVisibleRect,getGlobalVisibleRect的更多相关文章
- View的个得区域函数getHitRect,getDrawingRect,getLocalVisibleRect,getGlobalVisibleRect(*)
注意: OnCreate()函数中 调用下面函数,结果全为0,要等UI控件都加载完了才能得到绘制时的值. getHitRect 以父控件的左上为原点,计算当前view在父控件的区域,不管父控件在屏幕的 ...
- android应用程序中获取view 的位置
1. 相对位置: getLeft() , getRight(), getTop(), getBottom() 在Android中可以把left相当于X轴值, top相当于Y轴值, 通过这两个值Andr ...
- View:Android View的scrollTo(),scrollBy(),getScrollX(), getScrollY()的理解
Android系统手机屏幕的左上角为坐标系,同时y轴方向与笛卡尔坐标系的y轴方向想反.提供了 getLeft(), getTop(), getBottom(), getRight() 这些API来获取 ...
- Android 判断一个 View 是否可见 getLocalVisibleRect(rect) 与 getGlobalVisibleRect(rect)
Android 判断一个 View 是否可见 getLocalVisibleRect(rect) 与 getGlobalVisibleRect(rect) [TOC] 这两个方法的区别 View.ge ...
- getGlobalVisibleRect和getLocalVisibleRect
在看android官网的demo的时候遇到这两个api,开始不是很明白这两个方法的作用. 通过多次的调试和测试之后慢慢开始有了点眉目,为了防止以后忘记,以此博文为记. 作为测试的目的,我写了这样一个布 ...
- getHitRect获取点击控件的位置
public void getHitRect(Rect outRect) Added in API level 1 Hit rectangle in parent ...
- Android坐标系统
1 背景 去年有很多人私信告诉我让说说自定义控件,其实通观网络上的很多博客都在讲各种自定义控件,但是大多数都是授之以鱼,却很少有较为系统性授之于渔的文章,同时由于自己也迟迟没有时间规划这一系列文章, ...
- view坐标_ _ Android应用坐标系统全面详解
转:http://blog.csdn.net/yanbober/article/details/50419117 1 背景 去年有很多人私信告诉我让说说自定义控件,其实通观网络上的很多博客都在讲各种自 ...
- Android应用坐标系统全面具体解释
1 背景 去年有非常多人私信告诉我让说说自己定义控件,事实上通观网络上的非常多博客都在讲各种自己定义控件,可是大多数都是授之以鱼.却非常少有较为系统性授之于渔的文章,同一时候由于自己也迟迟没有时间规划 ...
随机推荐
- Yii2 多域名跨域同步登录退出
在平台开发过程中,项目分为前台(frontend)www.xxx.com和后台(backend) yun.xxx.com两部分,绑定两个域名, 我们知道在没有绑定域名的时候前后台可以同步登录和退出,但 ...
- JBPM学习(二):ProcessEngine与Service API
1.获取processEngine的方法: a) 方法一 private ProcessEngine processEngine = new Configuration().setResource(& ...
- 【14】在资源管理类中小心copying行为
1.为什么要使用资源管理类? 资源管理类的思路就是,栈上的对象,封装堆上分配的资源,确保一定会释放资源.auto_ptr和shared_ptr就是资源管理类,行为上像指针. 2.auto_ptr和sh ...
- mybatis完美的实战教程
文件夹(? )[-] (读者注:事实上这个应该叫做非常基础的入门一下下,假设你看过Hibernate了那这个就非常的简单) 文章来源:http://blog.csdn.net/techbirds_ba ...
- 用Python和FFmpeg查找大码率的视频文件
用Python和FFmpeg查找大码率的视频文件 本文使用Python2.7, 这个工作分两步 遍历目录下的视频文件 用ffprobe获取是视频文件的码率信息 用ffprobe 获取json格式的视频 ...
- careercup-位操作5.1
5.1 写程序使整数N中第i位到第j位的值与整数M中的相同. 题目 给定两个32位的数,N和M,还有两个指示位的数,i和j. 写程序使得N中第i位到第j位的值与M中的相同(即:M变成N的子串且位于N的 ...
- 图解如何用U盘重装系统
第一类方法: 原生U盘安装,本工具制作完的U盘启动菜单含Windows7操作系统安装功能,使用本功能可以将Win7系统完美移植到你的U盘中.本功能不用进PE不用虚拟光驱,不受FAT32和NTFS文件系 ...
- DNS 和 IPv6 配置攻略
Windows 2003 DNS配置攻略 http://lgzeng2360.blog.51cto.com/275998/161908/ http://ask.zol.com.cn/q/21861.h ...
- Asp.Net MVC 实用视频教程
[北盟学习BaMn.Cn] Asp.Net MVC 第01课--创建第一个项目.avi [北盟学习BaMn.Cn] Asp.Net MVC 第02课--自己建一个controller view.avi ...
- linux的nohup disown setsid screen
```nohup 可以将进程挂起 帐号退出时不受影响 nohup cp -r a b/ [>/~/cp.log] & setsid 作用类似于nohup swtsid cp -r a b ...