我们自定义view 时,不可避免要和Android坐标系打交道,昨天特意去分析实验了一下,记录下来。
首先是一个图
(三个矩形由小到大分别表示 View View所处的ViewGroup Screen屏幕)
首先Android屏幕的坐标系是和数学坐标系略有不同的
Android坐标系原点为屏幕左上角的顶点
X轴正方向向右,Y轴正方向向下
图中还有一些获取位置的get方法,这些方法可以分为两类:
View的坐标获取方法(红色线代表View方法的返回值含义):
getTop():获取view自身顶边到父布局顶边的距离
getBottom():获取View自身底边到父布局顶边的距离
getLeft():获取View自身左边到父布局左边的距离
getRight():获取View自身右边到父布局左边的距离
顺便补充一下:
getWidth()和getHeight() 是获取view自身的宽和高
这个图中间的橙色点,就是我们手指触摸的位置
也就是MotionEvent (蓝色线代表是MotionEvent方法获得的值)
MotionEvent提供的方法:
getX(): 获取点击事件距离该View左边的距离
getY(): 获取点击事件距离该View顶边的距离
getRawX(): 获取点击事件距离整个屏幕的左边的距离,绝对坐标
getRawY(): 获取点击事件距离整个屏幕的顶边的距离,绝对坐标(包括通知栏的高度)
然后我们再来看两个获取view位置的方法,先上图
黑色边框 代表的是整个手机屏幕
绿色边框 代表的是状态栏
蓝色边框 代表的是App
红色边框 代表的是App 默认的 TitleBar
橙色边框 代表的是View
View上方有两种颜色的线,代表两个方法获得的View的Y坐标
他们获得的X坐标都是相同的,因为App的左边缘和手机屏幕左边缘重合
但是他们的Y坐标各有不同
View.getLocationInWindow获得的是view在app这个window上的位置
之前我一直以为它是不含状态栏高度的,但是实际打印了一下,也包含状态栏的高度
这点查了一下,也没弄懂哪里不同,提问了,希望有人可以回答我
View.getLocationOnScreen获得的是view在整个手机屏幕上的位置(它获得的Y轴坐标和MotionEvent.getRawY()是一样的)
它是包含状态栏(通知栏)的高度的
关于这两个方法的使用,它们并不是有返回值的,而是靠传入一个引用来获得值
例如
int[] location = new int[2];
View.getLocationInWindow(location);
int ViewX = location[0];
int ViewY = location[1];
还有,因为Android默认为activity增加一个titleBar 所以你通过setContentView(layout) 设置的布局,都是在titleBar之下的。
如果想取消这个默认的TitleBar,有两种方式
一:在AndroidManifest.xml中加入一行语句
android:label="@string/app_name"
>
二:在activity中的onCreate方法中加入一行语句
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //这句
setContentView(R.layout.activity_main);
}
然后我写了一个程序来输出上述我说的这些结果,大家可以下载方便实验一下
Log截图
测试项目地址 https://github.com/Wizwizard/AndroidCoordinate
觉得有用的话,支持一下。。。因为我从来没见过有人评论我。。。