android – 如何将Touch Listeners传递给自定义视图进行拖放?

前端之家收集整理的这篇文章主要介绍了android – 如何将Touch Listeners传递给自定义视图进行拖放?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个关于处理CustomView触摸事件的问题.我正在动态地将自定义视图添加到布局(即FrameLayout).那些具有touchListeners的自定义视图用于在角落处拉点(如下图所示).除此之外我必须在屏幕上拖放整个视图,如果用户触摸除了那些角点之外(图像中的颜色区域)必须拖放视图,否则不会,以及如果用户触摸到外面查看我不想触发任何触摸侦听器.

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

@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,Cs表示这三条触摸线的基点.

然后用基点A定义边界线AB,用基点A定义AC(如果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

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

如果该因子t1大于1,则触摸点T位于A和I3之间,即“ta”线.如果因子t1小于1T,则位于线部分A-I3之外.

您必须使用行tb和c和tc以及a执行此操作三次.每次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”事件处理程序中调用一次.由于您知道您触摸了该区域,因此在移动手指时无需进行所有这些计算.

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

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

我的解决方案明星案例:

>定义尖峰三角形
>使用我前面提到的方法(通过解决一些LSE)来确定是否触摸了一个.

其他一切:

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

如果您正确处理和更新三角形组,则不应再有关于如何处理凹形的问题.

对于你的五角大楼尝试以下:

>使用快速船体和三角测量方法.>如果用户更改了点位置,请更新三角形>利润

原文链接:https://www.f2er.com/android/309209.html

猜你在找的Android相关文章