iPhone: отслеживание / идентификация отдельных штрихов - PullRequest
14 голосов
/ 27 мая 2009

У меня есть быстрый вопрос относительно отслеживания касаний на iPhone, и я, кажется, не могу прийти к выводу по этому вопросу, поэтому любые предложения / идеи очень ценятся:

Я хочу иметь возможность отслеживать и идентифицировать прикосновения на iphone, т.е. в основном каждое касание имеет начальную позицию и текущую / перемещенную позицию. Прикосновения хранятся в std :: vector, и они должны быть удалены из контейнера, как только они закончатся. Их положение будет обновляться после их перемещения, но я все еще хочу отслеживать, с чего они изначально начали (распознавание жестов).

Я получаю прикосновения от [event allTouches], дело в том, что NSSet не отсортирован, и мне кажется, что я не могу определить касания, которые уже сохранены в std :: vector, и обратиться к касаниям в NSSet (поэтому я знаю, какие из них закончились и будут удалены, или были перемещены и т. д.)

Вот мой код, который, конечно, отлично работает только одним пальцем на сенсорном экране, но с более чем одним я получаю непредсказуемые результаты ...

    - (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
    [self handleTouches:[event allTouches]];
}

- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
    [self handleTouches:[event allTouches]];
}

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    [self handleTouches:[event allTouches]];
}

- (void) touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
    [self handleTouches:[event allTouches]];
}

- (void) handleTouches:(NSSet*)allTouches
{   
    for(int i = 0; i < (int)[allTouches count]; ++i)
    {
        UITouch* touch = [[allTouches allObjects] objectAtIndex:i];
        NSTimeInterval timestamp = [touch timestamp];

        CGPoint currentLocation = [touch locationInView:self];
        CGPoint previousLocation = [touch previousLocationInView:self];

        if([touch phase] == UITouchPhaseBegan)
        {
            Finger finger;
            finger.start.x = currentLocation.x;
            finger.start.y = currentLocation.y;
            finger.end = finger.start;
            finger.hasMoved = false;
            finger.hasEnded = false;

            touchScreen->AddFinger(finger);
        }
        else if([touch phase] == UITouchPhaseEnded || [touch phase] == UITouchPhaseCancelled)
        {
            Finger& finger = touchScreen->GetFingerHandle(i);

            finger.hasEnded = true;
        }
        else if([touch phase] == UITouchPhaseMoved)
        {
            Finger& finger = touchScreen->GetFingerHandle(i);

            finger.end.x = currentLocation.x;
            finger.end.y = currentLocation.y;
            finger.hasMoved = true;
        }
    }

    touchScreen->RemoveEnded();
}

Спасибо!

Ответы [ 3 ]

8 голосов
/ 28 марта 2010

Похоже, что «правильный» способ отследить несколько касаний по значению указателя события UITouch.

Более подробную информацию вы можете найти в разделе «Обработка сложной последовательности Multi-Touch» этого Документация для разработчиков Apple

7 голосов
/ 27 мая 2009

Чтобы исправить вашу проблему, откажитесь от метода handleTouches. Первое, что вы делаете в методе handleTouches, это переключаете его на touchPhase, но это вам уже дано. Если вы получаете прикосновение в прикосновениях Began, вы знаете, что прикосновение в UITouchPhaseBegan. Объединяя касания из четырех методов касания в один метод, вы побеждаете цель иметь четыре метода делегата.

В каждом из этих способов Apple дает вам возможность работать с разными фазами текущего касания.

Во-вторых, вам не нужно искать событие для текущего касания, оно предоставляется вам в качестве параметра: касания.

Событие состоит из набора касаний. Для удобства вам даны текущие прикосновения, даже если они также могут быть найдены в событии.

Итак, в касаниях Началось, вы начинаете отслеживать касание.

    - (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{


        NSString *startPoint = NSStringFromCGPoint([[touches anyObject] locationInView:self]);  

        NSDictionary * touchData = [NSDictionary dictionaryWithObjectsandKeys: startPoint, @"location", touches, @"touch"]

        [startingLocations addObject:touchData];

        }

Я использую массив словарей для хранения сенсорных данных.

Попробуйте отделить ваш код и переместить его в соответствующий сенсорный метод. Что касается направления, у Apple есть пара примеров проектов, которые фокусируются на прикосновениях и показывают, как настроить эти методы.

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

Указатель на каждый набор касаний остается постоянным, только данные меняются.

Кроме того, я прочел бы раздел руководства по программированию для iPhone OS, посвященный обработке событий, который углубляется в то, что я сказал выше, с несколькими диаграммами, объясняющими связь касаний с событиями во времени.

Выдержка:

В iPhone OS объект UITouch представляет собой прикосновение, и UIEvent Объект представляет собой событие. Мероприятие объект содержит все сенсорные объекты для текущая мультитач последовательность и может предоставить сенсорные объекты, специфичные для вид или окно (см. Рисунок 3-2). сенсорный объект является постоянным для данного палец во время последовательности, и UIKit мутирует как он отслеживает палец во всем этом. Сенсорные атрибуты это изменение является фазой касание, его расположение в представлении, его предыдущее местоположение и его метка времени. Код обработки событий оценивает эти атрибуты, чтобы определить, как реагировать на мероприятие.

0 голосов
/ 27 мая 2009

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

В вашем -handleTouches методе вы можете поместить что-то вроде этого в цикл for:

// ..existing code..
CGPoint previousLocation = [touch previousLocationInView:self];

// Loop through previous touches
for (int j = 0; j < [previousTouchLocationArray count]; j++) {
  if (previousLocation == [previousTouchLocationArray objectAtIndex:j]) {
    // Current touch matches - retrieve from finger handle j and update position
  }
}

// If touch was not found, create a new Finger and associated entry 

Очевидно, что вам нужно будет поработать, чтобы интегрировать это в ваш код, но я уверен, что вы можете использовать эту идею для правильной идентификации касаний при их перемещении по экрану. Также я только что понял, что CGPoint не очень хорошо вписывается в NSArray - вам нужно обернуть их в объекты NSValue (или использовать другой тип массива).

...