参考自任玉刚先生的《Android开发艺术探索》
一、View的位置参数
在Android中,x轴和y轴的正方向分别为右和下。其中View的位置主要由它的四个顶点来决定,分别对应View的四个属性left、top、right和bottom,分别为左上角横坐标,左上角纵坐标,右下角横坐标和右下角纵坐标。这些坐标都是相对于View的父容器来说的,是相对坐标。如图所示
view的宽width = right - left;
view的高height = bottom - top;
在view的源码中,这四个属性分别对应着mLeft、mTop、mRight和mBottom这四个成员变量,获取方法如下:
Left = getLeft();
Right = getRight();
Top = getTop();
Bottom = getBottom();
从Android3.0开始,View增加了如下参数:x、y、translationX和translationY。其中x和y是view的左上角坐标(初始的时候x和y应该等于left和top的值),translationX和translationY是View左上角相对于父布局容器的偏移量,这四个参数全部都是相对于父布局的坐标,translationX和translationY的默认值为0。它们之间的关系为:
x = left + translationX;
y = top + translationY;
注意:
1、View在平移过程中,top和left表示是原始左上角的位置信息,也就是初始值,因此两个值无论是否有平移都是不会改变的。在移动过程中,发生改变的是translationX和translationY,因此x,y和跟着发生变化。
当需要获取view当前的x,y坐标时,通过View对象本身的api可以用getX(),getY(),来获取。此时返回的是当前view相对于其父布局而言左上角的x,y坐标。
2、当需要获取当前view相对于手机屏幕左上角的x,y坐标时,可以用这两个api:
getLocationOnScreen(int[2]) ,计算该视图在全局坐标系中的x,y值(绝对坐标)(注意这个值是要从屏幕顶端算起,也就是说包括了通知栏的高度)。
这里注意,还有这个方法:
getLocationInWindow(int[2]) ,计算该视图在它所在的父布局中的的坐标x,y值。
借用网上的一幅图:
我们看看这两个api的源码:
/**
* <p>Computes the coordinates of this view on the screen. The argument
* must be an array of two integers. After the method returns, the array
* contains the x and y location in that order.</p>
*
* @param outLocation an array of two integers in which to hold the coordinates
*/
public void getLocationOnScreen(@Size(2) int[] outLocation) {
getLocationInWindow(outLocation);
final AttachInfo info = mAttachInfo;
if (info != null) {
outLocation[0] += info.mWindowLeft;
outLocation[1] += info.mWindowTop;
}
}
/**
* <p>Computes the coordinates of this view in its window. The argument
* must be an array of two integers. After the method returns, the array
* contains the x and y location in that order.</p>
*
* @param outLocation an array of two integers in which to hold the coordinates
*/
public void getLocationInWindow(@Size(2) int[] outLocation) {
if (outLocation == null || outLocation.length < 2) {
throw new IllegalArgumentException("outLocation must be an array of two integers");
}
outLocation[0] = 0;
outLocation[1] = 0;
transformFromViewToWindowSpace(outLocation);
}
二、MotionEvent
在手指接触屏幕后产生的一系列事件,典型的有这几种:
ACTION_DOWN : 手指刚接触屏幕
ACTION_MOVE : 手指在屏幕上移动
ACTION_UP : 手指从屏幕上松开的瞬间
正常情况下,一次手指触摸屏幕的行为会引发一系列点击事件,比如:
1、点击屏幕后松开,事件顺序为DOWN -> UP;
2、点击屏幕滑动一会儿再松开,事件顺序为DOWN->MOVE->……->MOVE->UP;
当需要获取view当前的x,y坐标时,通过MotionEvent对象可以用getX(),getY(),来获取。此时返回的是当前view相对于其父布局而言左上角的x,y坐标。
当需要获取当前view相对于手机屏幕左上角的x,y坐标时,通过MotionEvent对象可以使用getRawX(),getRawY()。
综合上面的一、二两大点,这里我写了个综合了两点知识的一个demo,如下图:
红色的正方形的父布局是紫色的正方形,此时手机触摸并移动红色的正方形,红色正方形跟着手指移动。实现方式:
代码稍后。