【问题标题】:Android: Erratic behavior when Drawing rectangle using 2 multi touch pointsAndroid:使用 2 个多点触控点绘制矩形时出现异常行为
【发布时间】:2018-06-02 12:03:14
【问题描述】:

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

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;

【问题讨论】:

    标签: android canvas multi-touch


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-27
      • 2013-07-17
      • 2014-07-10
      • 2014-05-04
      • 2016-05-05
      • 2019-05-20
      • 2019-08-27
      相关资源
      最近更新 更多