首页 > 解决方案 > Android:使用 2 个多点触控点绘制矩形时出现异常行为

问题描述

在完成了一些关于触摸事件的教程并在画布上绘图后,我尝试结合所学知识并制作一个使用 2 个触摸点创建矩形的应用程序。我可以使用单个触摸点拖动并创建一个矩形,但是一旦我使用第二根手指,矩形就会开始表现得很奇怪,要么根本不绘制矩形,要么在拖动一点后消失。此外,例如,如果我通过使一个触摸点位于屏幕的左下角而另一个触摸点位于屏幕的右上角来绘制一个矩形,那么如果我将手指拖动到它们相互交叉的点,该矩形就会消失。

正在运行的应用程序的 gif

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;

标签: androidcanvasmulti-touch

解决方案


MotionEvent.ACTION_DOWN 只会在第一次触摸屏幕事件时发生。

“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。所以问题必须在你程序的其他地方。


推荐阅读