gpt4 book ai didi

android - 如何将触摸监听器传递给自定义 View 以进行拖放?

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:41:25 25 4
gpt4 key购买 nike

我有一个关于处理的问题 touch eventsCustomView .我正在将自定义 View 动态添加到布局(即 FrameLayout)。那些具有用于在角落处拉点的 touchListeners 的自定义 View (如下图所示)。除此之外,我必须将整个 View 拖放到屏幕上,如果用户触摸的不是那些角点(图像中的颜色区域),则必须拖放 View ,否则不会,并且如果用户触摸外面查看我不想触发任何触摸监听器。

Check This Image

我可以使用此代码提取这些点

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:

if (topTouchArea.contains(event.getX(), event.getY())) {
currentTouch = TOUCH_TOP;
} else if (RightTouchArea.contains(event.getX(),event.getY())) {
currentTouch = TOUCH_RIGHT;
} else if (LeftTouchArea.contains(event.getX(),event.getY())) {
currentTouch = TOUCH_LEFT;
} else {
return false; //Return false if user touches none of the corners
}
return true;
case MotionEvent.ACTION_MOVE:

switch (currentTouch) {
case TOUCH_TOP:
top.x = event.getX();
top.y = event.getY();
invalidate();
return true;
case TOUCH_RIGHT:
Right.x = event.getX();
Right.y = event.getY();
invalidate();
return true;
case TOUCH_LEFT:
Left.x = event.getX();
Left.y = event.getY();
invalidate();
return true;
}

case MotionEvent.ACTION_UP:

switch (currentTouch) {
case TOUCH_TOP:
top.x = event.getX();
top.y = event.getY();
invalidate();
currentTouch = NONE;
return true;
case TOUCH_RIGHT:
Right.x = event.getX();
Right.y = event.getY();
invalidate();
currentTouch = NONE;
return true;
case TOUCH_LEFT:
Left.x = event.getX();
Left.y = event.getY();
invalidate();
currentTouch = NONE;
return true;
}
return false;
}
return false;
}

我怎样才能实现这种拖放以及 CustomView 的上述字符....

最佳答案

我会使用一些线性代数来解决这个问题。您有 3 个或更多点不属于一条线(线性无关)。您可以使用此事实来确定接触点是否位于该区域内。您拥有的点越多,这会变得越困难,因此您需要将角数多于 3 的多边形转换为一组三角形,应用以下过程。

所以你有三个点 A,B,C 定义一个三角形。然后使用触摸点定义三条线以获得方向向量 AT、BT、CT,而 A、B、Cs 表示这三条触摸线的基点。

然后用基点 A 定义边界线 AB,用基点 A 定义边界线(A 或 C 是​​基点无关紧要),最后用基点 C 定义线 CB。所以让我们总结一下(大字母是表示向量,而小写字母表示标量或因子):

边界线 :

a:X=A+f1*AB
b:X=B+f2*BC
c:X=C+f3*AC

触控线 :
ta:X=A+t1*AT
tb:X=B+t2*BT
tc:X=C+t3*CT

Resulting triangle with touch lines and intersections

现在,您将接触线(图中的粉红色)与与接触线基点相对的边界线(绿色/红色)相交。例如,您需要将线 'ta' 与线 b 相交以获得交点 I3。如果将向量 AT 扩展因子 ,您将达到这一点。 t1 .

如果这个因素 t1 大于 1 时,接触点 T 位于 A 和 I3 线 'ta' 之间。 if 因子 t1 小于 1 T 位于线路部分 A-I3 之外。

您必须使用 tb 和 c 以及 tc 和 a 行执行此操作 3 次。每次 I(n) 点都需要小于 1(其中 n 在 {1,2,3} 中)。

如果此条件适用于所有三个交叉点,则您的接触点位于三角形内。

您将通过求解这些简单的方程组得到交集:

首先
A+t1*AT = B+f2*BC
<=>
0 = A+t1*AT - B - f2*BC

这个系统看起来像这样(其中 x,y 提供特定的坐标分量):
0 = xA + t1*(xT-xA) - xB - f2*(xC-xB)
0 = yA + t1*(yT-yA) - yB - f2*(yC-yB)

第二
B+t2*BT = C+f3*AC
<=>
0 = B+t2*BT - C - f3*AC

第三
C+t3*CT = A+f1*AB
<=>
0 = C+t3*CT - A - f1*AB

解决这三个系统将为您提供一个点是否在该区域内的答案。
解决方案需要明显不同于 0(如果 0 是唯一的解决方案,您的点在同一条线上 - > 线性相关)!

基于此,您可以翻译对象的所有坐标。

如上所述,您需要缩减为三角形并将此方法应用于多边形的所有子三角形。如果一个符合条件(或者两个或更多,如果您想实现多点触控),则您的触摸位于对象区域内。

这只是三个小计算,应该在“Touch-Down”事件处理程序中调用一次。由于您知道您触摸了该区域,因此无需在移动手指时进行所有这些计算。

关于三角化
这是一个更复杂的问题,不是一句话就能回答的。根据您对另一个答案的评论,您不想处理简单的多边形,而是想处理由多边形组成的更复杂的形状。例如你的星形。在这里你可以只使用上面的方法,你需要自己定义你的三角形。因为要知道哪个角属于人脸,哪个不属于,并不是那么简单。

另一种解决方案是使用所谓的 Quick Hull 算法从点集生成凸包。这将为您提供应用于三角形化的角点形状的轮廓。如果你有一些“无阴影”的面,只要处理它们,如果你真的想处理所有可能的点集。

我在你明星案例中的解决方案:
  • 定义尖峰三角形
  • 使用我前面提到的方法(通过解决一些 LSE)来确定一个人是否被触摸。

  • 对于其他一切:

    使用三角形的外接圆将其三角化。通过找到三个点来定义一个不包含任何其他轮廓点的圆。所谓的 Delaunay Triangulation .
    让这个方法找到你的三角形。如果您有一些未着色的区域,您可以定义一个具有“可触摸”属性或类似属性的三角形对象,让您的算法知道是否应该处理触摸。

    如果你正确处理和更新你的三角形集,就不会有关于如何处理凹形的问题了。

    对于您的五边形,请尝试以下操作:
  • 使用快速 shell 和三角测量方法。
  • 如果用户更改点位置,则更新三角形
  • 利润
  • 关于android - 如何将触摸监听器传递给自定义 View 以进行拖放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11137090/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com