Как кодировать для мультитач - PullRequest
8 голосов
/ 19 ноября 2010

Итак, я разрабатываю приложение, которое должно обрабатывать мультитач. В принципе, я хочу одно касание для поворота (это не проблема). И мультитач для прокрутки.

У меня есть основной код, но у меня возникают проблемы, когда происходит переход с одиночного на мультитач и наоборот. В основном движение будет толчковым, потому что среднее положение мультитача (два пальца) и абсолютное положение одного пальца находятся на расстоянии. Поэтому, если у меня два пальца на экране, они занимают срединное положение, а затем поднимают один палец, это будет похоже на быстрое перемещение из этого срединного положения в абсолютное положение одного пальца. Это будет движение, которое я не хочу.

Это мой код:

@Override
public boolean onTouchEvent( MotionEvent event ) {
    float xEvent[] = new float[ 2 ];
    float yEvent[] = new float[ 2 ];
    switch( event.getPointerCount() ) {
        case 1:
            xEvent[ 0 ] = event.getX( 0 );
            yEvent[ 0 ] = event.getY( 0 );
            switch( event.getAction() ) {
                case MotionEvent.ACTION_DOWN:
                    camera.onTouchDown( xEvent[ 0 ], yEvent[ 0 ] );
                    return true;
                case MotionEvent.ACTION_MOVE:
                    camera.onTouchRotate( xEvent[ 0 ], yEvent[ 0 ] );
                    return true;
                default: return super.onTouchEvent( event );
            }
        case 2:
            xEvent[ 0 ] = event.getX( 0 );
            yEvent[ 0 ] = event.getY( 0 );
            xEvent[ 1 ] = event.getX( 1 );
            yEvent[ 1 ] = event.getY( 1 );
            switch( event.getAction() ) {
                case MotionEvent.ACTION_DOWN:
                    camera.onTouchDown( ( ( xEvent[ 0 ] + xEvent[ 1 ] ) / 2 ), ( ( yEvent[ 0 ] + yEvent[ 1 ] ) / 2 ) );
                    return true;
                case MotionEvent.ACTION_MOVE:
                    camera.onTouchSlide( ( ( xEvent[ 0 ] + xEvent[ 1 ] ) / 2 ), ( ( yEvent[ 0 ] + yEvent[ 1 ] ) / 2 ) );
                    return true;
                case MotionEvent.ACTION_POINTER_1_UP:
                    camera.onTouchDown( xEvent[ 1 ], yEvent[ 1 ] );
                    return true;
                case MotionEvent.ACTION_POINTER_2_UP:
                    camera.onTouchDown( xEvent[ 0 ], yEvent[ 0 ] );
                    return true;
                default: return super.onTouchEvent( event );
            }
        default: return false;
    }
}

Функция onTouchDown камеры просто устанавливает первое значение касания. Вот почему я также использую его в движении вверх, чтобы установить новое начальное значение для движения одним касанием при выходе из мультитача.

Я надеюсь, что кто-то знает, в чем моя проблема, и может помочь мне в дальнейшем.

Ответы [ 2 ]

10 голосов
/ 20 ноября 2010

Начните здесь, если вы еще не прочитали его, он затрагивает несколько вопросов, касающихся мультитач в Android: http://android -developers.blogspot.com / 2010/06 / making-sense-of-multitouch.html

Несколько вещей о размещенном вами коде:

  1. Вы никогда не увидите ACTION_DOWN с количеством указателей 2. ACTION_DOWN отправляется толькодля первого указателя, который идет вниз.Все пальцы, которые касаются экрана после первого, отправят ACTION_POINTER_DOWN.
  2. Не допускайте, чтобы касание касалось только двух пальцев, их может быть больше.
  3. Работать намного прощес маскированным действием (используйте MotionEvent#getActionMasked()), чем для индивидуального кодирования каждого индекса указателя.
  4. В конце концов, индексы имеют значение только для извлечения данных из MotionEvent.Если вы отслеживаете движение указателя во времени, используйте идентификатор указателя.
  5. Идентификаторы указателя - это просто цифры.Не делайте предположений относительно того, какие значения они будут иметь, кроме того, что они будут целыми числами от 0 и выше.
2 голосов
/ 20 ноября 2010

Вы можете решить эту проблему с помощью простой математики, хотя, возможно, уже существует лучший способ.

Просто создайте объект, который удерживает позицию каждого пальца, когда происходит событие .ACTION_POINTER_X_UP, и логический объект, которыйсодержит тип сенсорного режима, который вы использовали в последний раз.

case MotionEvent.ACTION_POINTER_1_UP:
        camera.onTouchDown( xEvent[ 1 ], yEvent[ 1 ] );
        boolean usedMultiTouch = true;
        int x = event.getX(1);
        int y = event.getY(1);
        return true;

Далее ваш оператор ACTION_MOVE (внутри case = 1) сработает, когда пользователь переместит свой палец, когда он перешел от мульти к одиночному касанию.

Теперь, в зависимости от того, что вы хотите сделать, вы можете игнорировать один ход (булево значение - ваша проверка), пока не сработает событие .ACTION_UP, и вы не установите логическое значение в значение false

или

Вы вызываете метод, который выполняет некоторые математические операции на основе сохраненных значений местоположения и пальца, который все еще находится на экране.Математика должна быть довольно простой, но я не знаю, что ты на самом деле хочешь делать.

...