Android:使用2个多点触控绘制矩形时的不稳定行为

时间:2018-06-02 12:03:14

标签: android canvas multi-touch

在做了一些关于触摸事件和在画布上绘图的教程之后,我尝试将我学到的东西结合起来并制作一个使用2个触点创建矩形的应用程序。我能够使用单个触摸点拖动并创建一个矩形但是一旦我使用第二个手指,矩形开始表现奇怪,要么根本不绘制矩形,要么拖动它后消失。此外,例如,如果我通过让一个触摸点位于左下角而另一个触摸点位于屏幕的右上角来绘制矩形,则如果我将手指拖动到彼此交叉的点,则矩形消失。 / p>

gif of the application running

private float xDown = 0,yDown = 0, xUp = 0, yUp = 0;
boolean touched = false;


@Override
protected void onDraw (Canvas canvas)  {
    canvas.drawColor(Color.TRANSPARENT);
    if(touched) {
        canvas.drawRect(xDown, yDown, xUp, yUp, mPaint);

    }
}

@Override
public boolean onTouchEvent (MotionEvent event) {
    int fingers = event.getPointerCount();
    switch (event.getAction()){

        case MotionEvent.ACTION_DOWN:
            if (fingers == 1) {
                xDown = event.getX(0);
                yDown = event.getY(0);

                xUp = 0;
                yUp = 0;
            }
            if (fingers == 2) {
                xUp = event.getX(1);
                yUp = event.getY(1);
                xDown = event.getX(0);
                yDown = event.getY(0);
                touched = true;
            }
            break;
        case MotionEvent.ACTION_MOVE:
            if (fingers == 1) {
                xUp = event.getX();
                yUp = event.getY();
                touched = true;
            }
            if (fingers == 2) {
                xUp = event.getX(1);
                yUp = event.getY(1);
                xDown = event.getX(0);
                yDown = event.getY(0);
                touched = true;
            }
            break;
        case MotionEvent.ACTION_UP:
            if (fingers == 1) {
                xUp = event.getX();
                yUp = event.getY();
                touched = true;
            }

            if (fingers == 2) {
                xUp = event.getX(1);
                yUp = event.getY(1);
                xDown = event.getX(0);
                yDown = event.getY(0);
                touched = true;
            }

            break;
    }
    invalidate();
    return true;

1 个答案:

答案 0 :(得分:0)

MotionEvent.ACTION_DOWN仅在屏幕上出现 FIRST 触摸事件时发生。

“ ACTION_DOWN

getActionMasked()的常量:手势已开始...”(来自https://developer.android.com/reference/android/view/MotionEvent#ACTION_DOWN

对于您的 SECOND 或更多手指,您需要检查 ACTION_POINTER_DOWN

“ ACTION_POINTER_DOWN

getActionMasked()的常量:非主要指针已下降...”(来自https://developer.android.com/reference/android/view/MotionEvent#ACTION_POINTER_DOWN

由于只使用了两个手指,因此无需担心ActionIndex(getActionIndex())。触摸屏幕的第一根手指始终是 ACTION_DOWN ,之后的每次触摸都是 ACTION_POINTER_DOWN

在ACTION_UP上是相反的。每次修饰(最后一次修饰除外)均为ACTION_POINTER_UP,最后一次修饰为ACTION_UP。

注意:第一次触摸(ACTION_DOWN)始终为,索引为0。 索引将始终分配给触摸,直到从屏幕上删除触摸为止。由于您正在对索引进行硬编码,因此任何意外触摸屏幕都会导致意外结果。对于测试程序,这很好,但是您最终将需要处理索引。

示例:

  

手指1(ACTION_DOWN)触摸屏幕并获得0的索引。
  手指2(ACTION_POINTER_DOWN)触摸屏幕并获得1的食指。
  手指3(ACTION_POINTER_DOWN)触摸屏幕并获得2的食指。

     

将手指2(索引1)从屏幕上抬起(ACTION_POINTER_UP)

     

手指1(索引0)和手指3(索引2)仍在MotionEvent中,并且它们的索引仍分配给它们。

最简单的更改就是更改:

case MotionEvent.ACTION_DOWN:
   if (fingers == 1) {
...

收件人:

case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
   if (fingers == 1) {
...

并更改:

case MotionEvent.ACTION_UP:
   if (fingers == 1) {
...

收件人:

case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
   if (fingers == 1) {
...

因为您已经在处理手指计数和索引。

此更改将使您的代码“更正确”,因为它将捕获第二个DOWN和第一个UP,但不能解决您的问题。 ACTION_MOVE已经在移动两个接触点时捕获了它们,并且您已经在处理两个索引并分配了X和Y。因此问题必须在程序的其他地方。