Android: ошибочное поведение при рисовании прямоугольника с использованием двух точек мультитач - PullRequest
0 голосов
/ 02 июня 2018

Пройдя несколько уроков по сенсорным событиям и рисуя на холсте, я попытался объединить полученные знания и создать приложение, которое создает прямоугольник с использованием двух точек касания.Я могу перетащить и создать прямоугольник, используя одну точку касания, но как только я использую второй палец, прямоугольник начинает вести себя странно, либо вообще не рисует прямоугольник, либо исчезает после его небольшого перетаскивания.Кроме того, если, например, я рисую прямоугольник, когда одна точка касания находится в нижнем левом углу, а другая - в верхнем правом углу экрана, прямоугольник исчезает, если я перетаскиваю пальцы в точку, где они пересекаются.

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;

1 Ответ

0 голосов
/ 28 июля 2018

MotionEvent.ACTION_DOWN будет происходить только при событии касания FIRST к экрану.

"ACTION_DOWN

Константа для getActionMasked (): нажатый жест запущен... "(От https://developer.android.com/reference/android/view/MotionEvent#ACTION_DOWN)

Для ваших ВТОРОГО или более пальцев необходимо проверить на 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 .

OnACTION_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.Так что проблема должна быть в другом месте вашей программы.

...