彻底搞懂 Android View 坐标体系:从绝对坐标到相对视图坐标
在 Android 自定义 View 以及处理滑动冲突时,最容易让人头疼的就是各种各样的坐标计算。getX()、getRawX()、getLeft() 之间有什么区别?为什么滑着滑着数值就变了?
搞懂这些问题的前提是清晰划分 Android 中的两大坐标系:Android 屏幕坐标系 与 View 相对坐标系。本文将带你一次性理清它们的关系。
一、 Android 坐标系(绝对坐标)
Android 屏幕坐标系是以整个屏幕作为参照物的物理坐标系。
- 原点 (0, 0):屏幕左上角的顶点。
- X 轴正方向:原点水平向右。
- Y 轴正方向:原点垂直向下。

在此坐标系中,任何一个点的位置都是绝对的。通过 MotionEvent 的 getRawX() 和 getRawY() 获得的就是触摸点在 Android 坐标系中的绝对坐标。
二、 View 坐标系(相对坐标)
在布局与绘图时,我们更关心的是 View 之间的相对位置。View 坐标系是以父容器的左上角作为原点的相对坐标系。
1. View 的四个顶点顶点坐标
一个 View 的物理大小和位置主要由它的四个顶点(Top, Left, Right, Bottom)决定:
- Left (左):View 左边缘到其父布局左边缘的距离。
- Top (上):View 上边缘到其父布局上边缘的距离。
- Right (右):View 右边缘到其父布局左边缘的距离。
- Bottom (下):View 下边缘到其父布局上边缘的距离。

这四个值在 View 中对应了四个成员变量 mLeft、mTop、mRight、mBottom。我们可以通过以下 Getter 方法直接获取这组相对坐标:
getLeft()getTop()getRight()getBottom()
2. View 的宽度与高度
由相对坐标关系很容易推导出 View 的宽度(Width)与高度(Height)的计算公式:
在 Android SDK 的 View.java 源码中,对应实现也非常直接:
/**
* Return the width of your view.
*
* @return The width of your view, in pixels.
*/
@ViewDebug.ExportedProperty(category = "layout")
public final int getWidth() {
return mRight - mLeft;
}
/**
* Return the height of your view.
*
* @return The height of your view, in pixels.
*/
@ViewDebug.ExportedProperty(category = "layout")
public final int getHeight() {
return mBottom - mTop;
}NOTE
这里的
getWidth()/getHeight()得到的是 View 最终呈现在屏幕上的布局宽高。这与getMeasuredWidth()/getMeasuredHeight()(测量宽高)在概念上是不同的,虽然大多数情况下它们的值相等。
三、 触摸事件中的坐标:MotionEvent 坐标对比
在处理点击事件或手势滑动时,onTouchEvent(MotionEvent event) 中提供了两组获取触摸点坐标的方法。以屏幕中某个被触摸的 View 为例,两组坐标的含义如下:
| 方法 | 坐标类型 | 坐标系原点 | 物理含义 |
|---|---|---|---|
getX() | 视图坐标(相对) | 当前被触摸 View 的左上角 | 触摸点距离当前 View 左边缘的距离 |
getY() | 视图坐标(相对) | 当前被触摸 View 的左上角 | 触摸点距离当前 View 上边缘的距离 |
getRawX() | 屏幕坐标(绝对) | 整个手机屏幕的左上角 | 触摸点距离屏幕左边缘的距离 |
getRawY() | 屏幕坐标(绝对) | 整个手机屏幕的左上角 | 触摸点距离屏幕顶边缘的距离 |
实战应用场景
getX() / getY():通常用于实现 View 内部的局部滑动、绘图追踪、或者判断手指是否仍在控件的边界内。getRawX() / getRawY():通常用于实现全屏范围内的跟手拖动。因为在拖动 View 时,View 自身的位置会发生改变,使用getX() / getY()作为基准会导致坐标的计算源发生“抖动”,而getRawX() / getRawY()提供绝对的物理屏幕参考,能避免抖动问题。
四、 总结与延伸
掌握了这两套坐标系,你在面对诸如“计算 View 的滑动偏移量”或者“判断两个 View 是否重叠”等问题时,就能做到游刃有余。接下来,推荐阅读 实现 View 滑动的多种方式 了解如何基于坐标变化控制 View 的运动,或者阅读 View 的事件分发机制 了解点击事件是如何流向这些坐标区域的。