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

 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值