Android view的事件体系

参考自任玉刚先生的《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,如下图:
这里写图片描述
红色的正方形的父布局是紫色的正方形,此时手机触摸并移动红色的正方形,红色正方形跟着手指移动。实现方式:
代码稍后。

猜你喜欢

转载自blog.csdn.net/ww_bin/article/details/80725061