MotionEvent event
getX(), getY() 是表示View相对于自身左上角的 x,y 坐标. 不是屏幕可见区域的坐标,而是以view左上角为原点(0,0)的坐标系。
getRawX(),getRawY() 是表示相对于屏幕左上角的 x 坐标值(注意:这个屏幕左上角是手机屏幕左上角, 不管activity是否有titleBar或是否全屏幕)。
-------------------------------------------------------------------------------------------------------------------------------------
//获取View在当前屏幕内的绝对坐标, 相当于view的左上角的点在屏幕坐标系的坐标。计算该视图在全局坐标系中的x,y值,(注意这个值是要从屏幕顶端算起,也就是索包括了通知栏的高度)
final int[] location = new int[2];
view.getLocationOnScreen(location);
Event 的 getX、 getY,getRawX、getRawY 可以通过 getLocationOnScreen 来进行转换:
getX () == getRawX() - location[0]
getY () == getRawY() - location[1]
//使用例子:
//ListView的滚动条位置
lstView.setOnItemClickListener(new OnItemClickListener(){
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3){
int Pos[] = { -1, -1 }; //保存当前坐标的数组
arg1.getLocationOnScreen(Pos); //获取选中的 Item 在屏幕中的位置,以左上角为原点 (0, 0)
OldListY = (float) Pos[1]; //我们只取 Y 坐标就行了
}
});
在 setAdapter() 后恢复先前的位置:
lstView.setAdapter(adapter); // 重新绑定Adapter
lstView.setSelectionFromTop(index, (int) OldListY); // 恢复刚才的位置
------------------------------------------
Viwe的getLeft , getTop, getBottom, getRight, 这一组是获取View在直接父布局坐标系中的位置。
以父布局的左上角位置为原点的坐标系,bottom是view的底边在y轴上的位置,同理getTop是获得view的顶部在父坐标系y轴上的位置。
可能为负数。 可用于判断listView是否滑到最顶部:list.getChildAt(0).getTop() == 0
--------------------------------------------
getWidth, getHeight, View的长和宽, 是屏幕上可见的view的大小(布局文件指定)padding的大小是包含在width和height里面的,设置pading不会影响该view的widht和height
public final int getHeight() {
return mBottom - mTop;
}
--------------------------------------------
Rect r1 = new Rect();
view.getLocalVisibleRect(r1); //以该view的左上角点为坐标原点,该view的可视区域。
获取view的rect, left 和top为0, right和bottom是view的宽和高,相当于getWidth,getHeight
--------------------------------------------
Rect r2 = new Rect();
view.getGlobalVisibleRect(r2); // 获取view的各边在屏幕全局坐标系的位置,相当于getLeft等这一组函数,只是坐标系不一样。
-------------------------------------------
getScrollX, Return the scrolled left position of this view. This is the left edge of the displayed part of your view,in pixels.
view实际内容占的大小(画布上画的内容)可能远远超过其显示区域的大小(view布局大小),ScrollX,是当前显示区域的左边界在画布坐标系中的位置。
getScrollY, 同上。
scrollBy,scrollTo,移动画布,在画布坐标系上移动x,y轴位置,调整显示区域。
scrollBy(20)相当于画布向左移动了20px
-----------------------------------------------------------------------------------
源码中,由用户的点击事件坐标,找到目标view的过程:
在父view中根据event的坐标,计算处在那个子view的范围 :
Rect rect = new Rect();
mImg.getHitRect(rect); //得到的是在父坐标中的响应区域,可结合event.getX event.getY 来判断点击在哪个子view的响应范围内 rect.contains(x, y); /** * Hit rectangle in parent's coordinates * * @param outRect The hit rectangle of the view. */ public void getHitRect(Rect outRect) { outRect.set(mLeft, mTop, mRight, mBottom); }
public boolean dispatchTouchEvent(MotionEvent ev) { final float xf = ev.getX(); //view 的屏幕坐标,如果view没有scroll,是和画布坐标重合的 final float yf = ev.getY(); final float scrolledXFloat = xf + mScrollX; //加上滚动的值,转换为view的画布的坐标,这个坐标系是onMeasure和onLayout时用的坐标 final float scrolledYFloat = yf + mScrollY; final Rect frame = mTempRect; final int scrolledXInt = (int) scrolledXFloat; final int scrolledYInt = (int) scrolledYFloat; final View[] children = mChildren; final int count = mChildrenCount; for (int i = count - 1; i >= 0; i--) { //遍历子view final View child = children[i]; child.getHitRect(frame); //返回该子view的mLeft, mTop, mRight, mBottom值,这些值是onLayout的时候设上去的 if (frame.contains(scrolledXInt, scrolledYInt)) { // 事件坐标是否落在该子view区域内 // offset the event to the view's coordinate system final float xc = scrolledXFloat - child.mLeft; //将事件的坐标由父view坐标系,转为子view的坐标系(都是画布坐标系) final float yc = scrolledYFloat - child.mTop; ev.setLocation(xc, yc); child.dispatchTouchEvent(ev) } } }