android dispatchTouchEvent方法查找包含点击坐标的view;

来源:互联网 发布:程序员能自学吗 编辑:程序博客网 时间:2024/05/01 15:25

 for (int i = childrenCount - 1; i >= 0; i--) {

...............

 if (!canViewReceivePointerEvents(child)
                                    || !isTransformedTouchPointInView(x, y, child, null)) {
                                ev.setTargetAccessibilityFocus(false);
                                continue;
                            }

...............

}

    /**     * Returns true if a child view contains the specified point when transformed     * into its coordinate space.     * Child must not be null.     * @hide     */   protected boolean isTransformedTouchPointInView(float x, float y, View child,            PointF outLocalPoint) {        final float[] point = getTempPoint();        point[0] = x;        point[1] = y;        transformPointToViewLocal(point, child);        //判断坐标在不在view中       final boolean isInView = child.pointInView(point[0], point[1]);        //outLocalpoint在拖拽事件中用到;        if (isInView && outLocalPoint != null) {            outLocalPoint.set(point[0], point[1]);        }        return isInView;    }
    /**     * @hide     */    //转换成view坐标系的坐标; public void transformPointToViewLocal(float[] point, View child) {        //这个是把触摸点转换为相对于孩子左上角的坐标;       point[0] += mScrollX - child.mLeft;        point[1] += mScrollY - child.mTop;        if (!child.hasIdentityMatrix()) {        //图像的内部进行了变换:如平移,旋转等; point位置应该是view经过matrix映射后的点,因此要用逆矩阵来映射;点击区域即使在view内部,point计算出来         //后,也可能不在view内部;        child.getInverseMatrix().mapPoints(point);        }    }
/** * Determines whether the given point, in local coordinates is inside the view. *//*package*/ final boolean pointInView(float localX, float localY) {    return localX >= 0 && localX < (mRight - mLeft)            && localY >= 0 && localY < (mBottom - mTop);}



映射坐标的方法:

顺时针旋转:

 


图为 (x0,y0) 顺时针旋转变换为(x1,y1);

x0 = r*cos α;

y0 = r*sin α;

x1 = r*cos(α+θ) = x0/cos α *cos α*cosθ -y0/sin α*sin α*sin θ) =x0*cosθ-y0*sinθ  ;

y1 = r*sin(α+θ) ;

转换矩阵

x1       cos θ -sin θ   0      x0

y1  =   sin θ   cos θ  0  *   y0

1          0       0        1       1

;

平移:

x1       1   0    Δx      x0

y1  =   0   1    Δy  *   y0

1         0   0    1       1


缩放:

x1         a   0    0      x0

y1  =     0   b    0   *   y0

1           0   0   1       1     

复合变换

设: 图形变换顺序为 x1,x2,x3..xn; 对应变换 矩阵为T1,T2,....Tn; 则矩阵相乘的顺序为:Tn*Tn-1*...T1;

android中Matrix提供的变换方法;

   /**
     * Preconcats the matrix with the specified rotation.
     * M' = M * R(degrees, px, py)
     */
    public boolean preRotate(float degrees, float px, float py) {
        native_preRotate(native_instance, degrees, px, py);
        return true;
    }

通过上面可以看出: scrollTo方法设置滚动过程不影响触摸事件分发; 因为每一次当前View滚动后:内容的触摸事件都会通过 point[0] += mScrollX - child.mLeft;

把point相对于View坐标系,转化为相对于View内容坐标系坐标;因此不影响滚动;

另外ScrollTo也只是走绘制过程;






0 0
原创粉丝点击