Устройства распознавания жеста

Устройства распознавания жеста преобразовывают низкоуровневый код обработки событий в высокоуровневые действия. Они - объекты, которые Вы присоединяете к представлению, позволяющему представлению реагировать на действия путем, управление делает. Устройства распознавания жеста интерпретируют касания, чтобы определить, соответствуют ли они определенному жесту, такому как сильно ударение, повышение или вращение. Если они распознают свой присвоенный жест, они отправляют сообщение действия в целевой объект. Целевой объект обычно является контроллером представления представления, реагирующим на жест как показано на рисунке 1-1. Этот шаблон разработки и мощен и прост; можно динамично определить, на какие действия представление отвечает, и можно добавить устройства распознавания жеста к представлению, не имея необходимость разделять представление на подклассы.

Рисунок 1-1  устройство распознавания жеста, присоединенное к представлению

Используйте устройства распознавания жеста для упрощения обработки событий

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

Если Вы хотите, чтобы Ваше приложение распознало уникальный жест, такой как галочка или кружащееся движение, можно создать собственное устройство распознавания жеста. Чтобы учиться как разработке и реализации Ваше собственное устройство распознавания жеста, посмотрите Создание Пользовательского Устройства распознавания Жеста.

Встроенные устройства распознавания жеста распознают общие жесты

При разработке приложения рассмотрите, какие жесты Вы хотите включить. Затем для каждого жеста определите, достаточно ли одно из предопределенных устройств распознавания жеста, перечисленных в Таблице 1-1.

Табличные 1-1  классы устройства распознавания Жеста платформы UIKit

Жест

Класс UIKit

Ответвление (любое число касаний)

UITapGestureRecognizer

Зажимание в и (для изменения масштаба представления)

UIPinchGestureRecognizer

Панорамирование или перетаскивание

UIPanGestureRecognizer

Сильный удар (в любом направлении)

UISwipeGestureRecognizer

Вращение (пальцы, перемещающиеся в противоположные направления)

UIRotationGestureRecognizer

Долго нажимайте (также известный как “касание и содержите”),

UILongPressGestureRecognizer

Ваше приложение должно реагировать на жесты только способами, которыми ожидают пользователи. Например, повышение должно увеличить и уменьшить масштаб, тогда как касание должно выбрать что-то. Для инструкций о том, как должным образом использовать жесты, см., что Приложения Реагируют на Жесты, Не Щелчки.

Устройства распознавания жеста присоединены к представлению

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

Триггерные сообщения действия жестов

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

Дискретные и непрерывные жесты

Жесты или дискретны или непрерывны. Один раз дискретный жест, такой как касание, происходит. Непрерывный жест, такой как зажимание, имеет место в течение времени. Для дискретных жестов устройство распознавания жеста отправляет его цели единственное сообщение действия. Устройство распознавания жеста для непрерывных жестов продолжает отправлять сообщения действия в свою цель до мультисенсорных концов последовательности, как показано на рисунке 1-2.

Рисунок 1-2  Дискретные и непрерывные жесты

Ответ на события с устройствами распознавания жеста

Существует три вещи, которые Вы делаете для добавления встроенного устройства распознавания жеста к приложению:

  1. Создайте и сконфигурируйте экземпляр устройства распознавания жеста.

    Этот шаг включает присвоение цели, действия и иногда присвоения специфичных для жеста атрибутов (такой как numberOfTapsRequired).

  2. Присоедините устройство распознавания жеста к представлению.

  3. Реализуйте метод действия, обрабатывающий жест.

Используя интерфейсного разработчика для добавления устройства распознавания жеста к приложению

В Интерфейсном Разработчике в XCode добавьте устройство распознавания жеста к своему приложению тем же путем, Вы добавляете, что любой объект к Вашему пользовательскому интерфейсу — перетаскивает устройство распознавания жеста от библиотеки объектов до представления. Когда Вы делаете это, устройство распознавания жеста автоматически становится присоединенным к тому представлению. Можно проверить, к какому представлению устройство распознавания жеста присоединено, и, если необходимо, измените соединение в файле пера.

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

Перечисление 1-1  , Добавляющее устройство распознавания жеста к Вашему приложению с Интерфейсным Разработчиком

@interface APLGestureRecognizerViewController ()
@property (nonatomic, strong) IBOutlet UITapGestureRecognizer *tapRecognizer;
@end
 
@implementation
- (IBAction)displayGestureForTapRecognizer:(UITapGestureRecognizer *)recognizer
     // Will implement method later...
}
@end

Добавление устройства распознавания жеста программно

Можно создать устройство распознавания жеста программно путем выделения и инициализации экземпляра бетона UIGestureRecognizer подкласс, такой как UIPinchGestureRecognizer. При инициализации устройства распознавания жеста укажите целевой объект и селектор действия, как в Перечислении 1-2. Часто, целевой объект является контроллером представления представления.

При создании устройства распознавания жеста программно необходимо присоединить его к представлению с помощью addGestureRecognizer: метод. Перечисление 1-2 создает единственное устройство распознавания жеста касания, указывает, что одно касание требуется для жеста быть распознанным, и затем присоединяет объект устройства распознавания жеста к представлению. Как правило, Вы создаете устройство распознавания жеста в своем контроллере представления viewDidLoad метод, как показано в Перечислении 1-2.

Перечисление 1-2  , Создающее единственное устройство распознавания жеста касания программно

- (void)viewDidLoad {
     [super viewDidLoad];
 
     // Create and initialize a tap gesture
     UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
          initWithTarget:self action:@selector(respondToTapGesture:)];
 
     // Specify that the gesture must be a single tap
     tapRecognizer.numberOfTapsRequired = 1;
 
     // Add the tap gesture recognizer to the view
     [self.view addGestureRecognizer:tapRecognizer];
 
     // Do any additional setup after loading the view, typically from a nib
}

Ответ на дискретные жесты

При создании устройства распознавания жеста Вы подключаете устройство распознавания к методу действия. Используйте этот метод действия реагировать на Ваш жест устройства распознавания жеста. Перечисление 1-3 обеспечивает пример ответа на дискретный жест. Когда пользователь касается представления, что устройство распознавания жеста присоединено, контроллер представления выводит на экран представление изображения, говорящее «Касание». showGestureForTapRecognizer: метод определяет расположение жеста в представлении от устройства распознавания locationInView: свойство и затем выводит на экран изображение в том расположении.

Перечисление 1-3  , Обрабатывающее двойной жест касания

- (IBAction)showGestureForTapRecognizer:(UITapGestureRecognizer *)recognizer {
       // Get the location of the gesture
      CGPoint location = [recognizer locationInView:self.view];
 
       // Display an image view at that location
      [self drawImageForGestureRecognizer:recognizer atPoint:location];
 
       // Animate the image view so that it fades out
      [UIView animateWithDuration:0.5 animations:^{
           self.imageView.alpha = 0.0;
      }];
}

Каждое устройство распознавания жеста имеет свой собственный набор свойств. Например, в Перечислении 1-4, showGestureForSwipeRecognizer: метод использует сильно ударить устройство распознавания жеста direction свойство, чтобы определить, сильно ударил ли пользователь налево или вправо. Затем это использует то значение, чтобы заставить изображение постепенно исчезнуть в том же направлении как сильно ударение.

Перечисление 1-4  , Отвечающее на левое или правое, сильно ударяет жест

// Respond to a swipe gesture
- (IBAction)showGestureForSwipeRecognizer:(UISwipeGestureRecognizer *)recognizer {
       // Get the location of the gesture
       CGPoint location = [recognizer locationInView:self.view];
 
       // Display an image view at that location
       [self drawImageForGestureRecognizer:recognizer atPoint:location];
 
       // If gesture is a left swipe, specify an end location
       // to the left of the current location
       if (recognizer.direction == UISwipeGestureRecognizerDirectionLeft) {
            location.x -= 220.0;
       } else {
            location.x += 220.0;
       }
 
       // Animate the image view in the direction of the swipe as it fades out
       [UIView animateWithDuration:0.5 animations:^{
            self.imageView.alpha = 0.0;
            self.imageView.center = location;
       }];
}

Ответ на непрерывные жесты

Непрерывные жесты позволяют Вашему приложению реагировать на жест, как это происходит. Например, Ваше приложение может масштабировать, в то время как пользователь зажимает, или позвольте пользователю перетаскивать объект вокруг экрана.

Перечисление 1-5 выводит на экран «Поворачивать» изображение в том же углу вращения как жест, и когда пользователь остановки вращаться, анимирует изображение, таким образом, это постепенно исчезает на месте при вращении назад к горизонтали. Поскольку пользователь поворачивает пальцы, showGestureForRotationRecognizer: метод вызывают постоянно, пока не шевелят обоими пальцами.

Перечисление 1-5  , Отвечающее на жест вращения

// Respond to a rotation gesture
- (IBAction)showGestureForRotationRecognizer:(UIRotationGestureRecognizer *)recognizer {
       // Get the location of the gesture
       CGPoint location = [recognizer locationInView:self.view];
 
       // Set the rotation angle of the image view to
       // match the rotation of the gesture
       CGAffineTransform transform = CGAffineTransformMakeRotation([recognizer rotation]);
       self.imageView.transform = transform;
 
       // Display an image view at that location
       [self drawImageForGestureRecognizer:recognizer atPoint:location];
 
      // If the gesture has ended or is canceled, begin the animation
      // back to horizontal and fade out
      if (([recognizer state] == UIGestureRecognizerStateEnded) || ([recognizer state] == UIGestureRecognizerStateCancelled)) {
           [UIView animateWithDuration:0.5 animations:^{
                self.imageView.alpha = 0.0;
                self.imageView.transform = CGAffineTransformIdentity;
           }];
      }
 
}

Каждый раз, когда метод вызывают, изображение установлено быть непрозрачным в drawImageForGestureRecognizer: метод. Когда жест завершен, изображение установлено быть прозрачным в animateWithDuration: метод. showGestureForRotationRecognizer: метод определяет, завершен ли жест путем проверки состояния устройства распознавания жеста. Эти состояния объяснены более подробно в Устройствах распознавания Жеста, Работают в Конечном автомате.

Определение, как взаимодействуют устройства распознавания жеста

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

Устройства распознавания жеста работают в конечном автомате

Переход устройств распознавания жеста от одного состояния до другого предопределенным способом. От каждого состояния они могут переместиться в одно из нескольких возможных следующих состояний на основе того, соблюдают ли они определенные условия. Точный конечный автомат варьируется в зависимости от того, дискретно ли устройство распознавания жеста или непрерывно, как проиллюстрировано на рисунке 1-3. Все устройства распознавания жеста запускаются в Возможном состоянии (UIGestureRecognizerStatePossible). Они анализируют любые мультисенсорные последовательности, которые они получают, и во время анализа они или распознают или не удаются распознать жест. Сбой распознать жест означает переходы устройства распознавания жеста к Состоянию отказа (UIGestureRecognizerStateFailed).

  Конечные автоматы рисунка 1-3 для устройств распознавания жеста

Когда дискретное устройство распознавания жеста распознает свой жест, переходы устройства распознавания жеста от Возможного до Распознанного (UIGestureRecognizerStateRecognized) и распознавание завершено.

Для непрерывных жестов Начались переходы устройства распознавания жеста от Возможного до (UIGestureRecognizerStateBegan) когда сначала распознан жест. Затем это переходит от, Начался до Измененного (UIGestureRecognizerStateChanged), и продолжает перемещаться от Измененного до Измененного, поскольку происходит жест. Когда последним пальцем пользователя шевелят от представления, переходов устройства распознавания жеста к Законченному состоянию (UIGestureRecognizerStateEnded) и распознавание завершено. Обратите внимание на то, что Законченное состояние является псевдонимом для Распознанного состояния.

Устройство распознавания для непрерывного жеста может также перейти от Измененного до Отмененного (UIGestureRecognizerStateCancelled) если это решает, что жест больше не соответствует ожидаемому образцу.

Каждый раз, когда устройство распознавания жеста изменяет состояние, устройство распознавания жеста отправляет сообщение действия в свою цель, если это не переходит к Неработающему или Отмененному. Таким образом дискретное устройство распознавания жеста отправляет только единственное сообщение действия, когда это переходит от Возможного до Распознанного. Непрерывное устройство распознавания жеста отправляет много сообщений действия, поскольку оно изменяет состояния.

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

Взаимодействие с другими устройствами распознавания жеста

Представление может иметь больше чем одно устройство распознавания жеста, присоединенное к нему. Используйте представление gestureRecognizers свойство для определения, какие устройства распознавания жеста присоединены к представлению. Можно также динамично измениться, как представление обрабатывает жесты путем добавления или удаления устройства распознавания жеста из представления с addGestureRecognizer: и removeGestureRecognizer: методы, соответственно.

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

  • Укажите, что одно устройство распознавания жеста должно проанализировать касание перед другим устройством распознавания жеста.

  • Позвольте двум устройствам распознавания жеста работать одновременно.

  • Препятствуйте тому, чтобы устройство распознавания жеста анализировало касание.

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

Объявление определенного порядка на два устройства распознавания жеста

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

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

Вы указываете этот тип отношения между двумя устройствами распознавания жеста путем вызова requireGestureRecognizerToFail: метод на устройстве распознавания жеста, которое Вы хотите задержать, как в Перечислении 1-6. В этом перечислении оба устройства распознавания жеста присоединены к тому же представлению.

  Устройство распознавания жеста Панорамирования перечисления 1-6 требует, чтобы сильно ударить устройство распознавания жеста перестало работать

- (void)viewDidLoad {
       [super viewDidLoad];
       // Do any additional setup after loading the view, typically from a nib
       [self.panRecognizer requireGestureRecognizerToFail:self.swipeRecognizer];
}

requireGestureRecognizerToFail: метод отправляет сообщение в получатель и указывает некоторый otherGestureRecognizer, который должен перестать работать, прежде чем устройство распознавания получения может начаться. В то время как это ожидает другого устройства распознавания жеста для перехода к Состоянию отказа, устройство распознавания получения остается в Возможном состоянии. Если другое устройство распознавания жеста перестало работать, устройство распознавания получения анализирует сенсорное событие и перемещается в его следующее состояние. С другой стороны, если другие переходы устройства распознавания жеста к Распознанному или Начались, устройство распознавания получения перемещается в Состояние отказа. Для получения информации об изменениях состояния посмотрите, что Устройства распознавания Жеста Работают в Конечном автомате.

Препятствование тому, чтобы устройства распознавания жеста анализировали касания

Можно изменить поведение устройства распознавания жеста путем добавления объекта делегата к устройству распознавания жеста. UIGestureRecognizerDelegate протокол обеспечивает несколько способов, которыми можно препятствовать тому, чтобы устройство распознавания жеста анализировало касания. Вы используете любого gestureRecognizer:shouldReceiveTouch: метод или gestureRecognizerShouldBegin: метод — оба - дополнительные методы UIGestureRecognizerDelegate протокол.

Когда касание начинается, если можно сразу определить, должно ли устройство распознавания жеста полагать, что касание, используйте gestureRecognizer:shouldReceiveTouch: метод. Этот метод вызывают каждый раз, когда существует новое касание. Возврат NO препятствует тому, чтобы устройство распознавания жеста было уведомлено, что произошло касание. Значение по умолчанию YES. Этот метод не изменяет состояние устройства распознавания жеста.

Перечисление 1-7 использует gestureRecognizer:shouldReceiveTouch: метод делегата препятствовать тому, чтобы устройство распознавания жеста касания получило касания, которые являются в пользовательском подпредставлении. Когда касание происходит, gestureRecognizer:shouldReceiveTouch: метод вызывают. Это определяет, коснулся ли пользователь пользовательского представления, и если так, препятствует тому, чтобы устройство распознавания жеста касания получило сенсорное событие.

Перечисление 1-7  , Препятствующее тому, чтобы устройство распознавания жеста получило касание

- (void)viewDidLoad {
    [super viewDidLoad];
    // Add the delegate to the tap gesture recognizer
    self.tapGestureRecognizer.delegate = self;
}
 
// Implement the UIGestureRecognizerDelegate method
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    // Determine if the touch is inside the custom subview
    if ([touch view] == self.customSubview){
        // If it is, prevent all of the delegate's gesture recognizers
        // from receiving the touch
        return NO;
    }
    return YES;
}

Если необходимо ожидать максимально долго прежде, чем решить, должно ли устройство распознавания жеста проанализировать касание, используйте gestureRecognizerShouldBegin: метод делегата. Если у Вас есть a, Обычно Вы используете этот метод UIView или UIControl подкласс с пользовательской сенсорной обработкой событий, конкурирующей с устройством распознавания жеста. Возврат NO заставляет устройство распознавания жеста сразу перестать работать, который позволяет другой сенсорной обработке продолжаться. Этот метод вызывают, когда устройство распознавания жеста пытается перейти из Возможного состояния, если распознавание жеста препятствовало бы тому, чтобы представление или управление получили касание.

Можно использовать gestureRecognizerShouldBegin:UIView метод, если Ваш контроллер представления или представления не может быть делегатом устройства распознавания жеста. Сигнатура метода и реализация являются тем же.

Разрешение одновременного распознавания жеста

По умолчанию два устройства распознавания жеста не могут распознать свои соответствующие жесты одновременно. Но предположите, например, что Вы хотите, чтобы пользователь был в состоянии зажать и повернуть представление одновременно. Необходимо изменить поведение по умолчанию путем реализации gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: метод, дополнительный метод UIGestureRecognizerDelegate протокол. Когда один анализ устройства распознавания жеста жеста блокировал бы другое устройство распознавания жеста от распознавания его жеста, или наоборот, этот метод вызывают. Этот метод возвраты NO по умолчанию. Возвратиться YES когда Вы хотите, чтобы два устройства распознавания жеста проанализировали свои жесты одновременно.

Указание одностороннего отношения между двумя устройствами распознавания жеста

Если Вы хотите управлять, как два устройства распознавания взаимодействуют друг с другом, но необходимо указать одностороннее отношение, можно переопределить любого canPreventGestureRecognizer: или canBePreventedByGestureRecognizer: методы подклассов возвратиться NO (значение по умолчанию YES). Например, если Вы хотите, чтобы жест вращения предотвратил жест повышения, но Вы не хотите, чтобы жест повышения предотвратил жест вращения, Вы указали бы:

[rotationGestureRecognizer canPreventGestureRecognizer:pinchGestureRecognizer];

и переопределите метод подклассов устройства распознавания жеста вращения возвратиться NO. Для получения дополнительной информации о том, как разделить на подклассы UIGestureRecognizer, посмотрите Создание Пользовательского Устройства распознавания Жеста.

Если никакой жест не должен предотвращать другой, используйте gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: метод, как описано в Разрешении Одновременного Распознавания Жеста. По умолчанию жест повышения предотвращает вращение и наоборот потому что два жеста не могут быть распознаны одновременно.

Взаимодействие с другими средствами управления пользовательским интерфейсом

В iOS 6.0 и позже, действия управления по умолчанию предотвращают перекрывающееся поведение устройства распознавания жеста. Например, действие по умолчанию для кнопки является единственным касанием. Если у Вас есть единственное устройство распознавания жеста касания, присоединенное к родительскому представлению кнопки, и пользователь касается кнопки, то метод действия кнопки получает сенсорное событие вместо устройства распознавания жеста. Это применяется только к распознаванию жеста, перекрывающему действие по умолчанию для управления, включающего:

  • Единственный палец единственное касание на a UIButton, UISwitch, UIStepper, UISegmentedControl, и UIPageControl.

  • Единственный палец сильно ударяет на кнопке a UISlider, в направлении параллельны к ползунку.

  • Единственный жест панорамирования пальца на кнопке a UISwitch, в направлении параллельны к переключателю.

Если у Вас есть пользовательский подкласс одних из этих средств управления, и Вы хотите изменить действие по умолчанию, присоединить устройство распознавания жеста непосредственно к управлению вместо к родительскому представлению. Затем устройство распознавания жеста получает сенсорное событие сначала. Как всегда, убедиться считать Инструкции по Интерфейсу пользователя iOS, чтобы гарантировать, что Ваше приложение предлагает интуитивный пользовательский опыт, особенно при переопределении поведения по умолчанию стандартного управления.

Устройства распознавания жеста интерпретируют сенсорные события сырых данных

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

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

В iOS касание является присутствием или перемещением пальца на экране. Жест имеет одно или более касаний, представленных UITouch объекты. Например, близкий к повышению жест имеет два касания — два пальца на экране, перемещающемся друг к другу от противоположных направлений.

Событие охватывает все касания, происходящие во время мультисенсорной последовательности. Мультисенсорная последовательность начинается, когда палец касается экрана и заканчивается, когда шевелят последним пальцем. Когда палец перемещается, iOS отправляет сенсорные объекты в событие. Мультисенсорное событие представлено a UIEvent объект типа UIEventTypeTouches.

Каждый сенсорный объект отслеживает только один палец и длится только пока мультисенсорная последовательность. Во время последовательности UIKit отслеживает палец и обновляет атрибуты сенсорного объекта. Эти атрибуты включают фазу касания, его расположения в представлении, его предыдущего расположения и его метки времени.

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

Рисунок 1-4  мультисенсорная последовательность и сенсорные фазы
A multi-touch sequence and touch phasesA multi-touch sequence and touch phases

Приложение получает касания в Сенсорных Методах обработки

Когда существуют новые или измененные касания для данной сенсорной фазы, во время мультисенсорной последовательности приложение отправляет эти сообщения; это вызывает

  • touchesBegan:withEvent: метод, когда один или несколько пальцев приземляются на экране.

  • touchesMoved:withEvent: метод, когда перемещаются один или несколько пальцев.

  • touchesEnded:withEvent: метод, когда один или несколько пальцев поднимаются с экрана.

  • touchesCancelled:withEvent: метод, когда сенсорная последовательность отменяется системным событием, таким как входящий телефонный вызов.

Каждый из этих методов связан с сенсорной фазой; например, touchesBegan:withEvent: метод связан с UITouchPhaseBegan. Фаза сенсорного объекта сохранена в фаза свойство.

Регулирование поставки касаний к представлениям

Могут быть времена, когда Вы хотите, чтобы представление получило касание перед устройством распознавания жеста. Но, прежде чем можно изменить путь поставки касаний к представлениям, необходимо понять поведение по умолчанию. В простом случае, когда касание происходит, сенсорный объект передается от UIApplication возразите против UIWindow объект. Затем окно сначала отправляет, касания к любым устройствам распознавания жеста присоединили представление, где касания произошли (или к суперпредставлениям того представления), прежде чем это передаст касание самому объекту представления.

  Поставка Значения по умолчанию рисунка 1-5 соединяет каналом для сенсорных событий

Устройства распознавания жеста получают первую возможность распознать касание

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

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

  Последовательность рисунка 1-6 сообщений для касаний
  1. Окно представляет два сенсорных объекта, Начал фазу — через touchesBegan:withEvent: метод — к устройству распознавания жеста. Устройство распознавания жеста еще не распознает жест, таким образом, его состояние Возможно. Окно отправляет эти те же касания в представление, что устройство распознавания жеста присоединено.

  2. Окно отправляет два сенсорных объекта в Перемещенной фазе — через touchesMoved:withEvent: метод — к устройству распознавания жеста. Устройство распознавания все еще не обнаруживает жест и находится все еще в Возможном состоянии. Окно тогда отправляет эти касания в присоединенное представление.

  3. Окно отправляет один сенсорный объект в Законченной фазе — через touchesEnded:withEvent: метод — к устройству распознавания жеста. Этот сенсорный объект не приводит к достаточной информации для жеста, но окно удерживает объект от присоединенного представления.

  4. Окно отправляет другой сенсорный объект в Законченной фазе. Устройство распознавания жеста теперь распознает свой жест, таким образом, оно устанавливает свое состояние в Распознанный. Непосредственно перед тем, как первое сообщение действия отправляется, представление вызывает touchesCancelled:withEvent: метод для лишения законной силы сенсорных объектов ранее представил Начинание и Перемещенные фазы. Касания в Законченной фазе отменяются.

Теперь предположите, что устройство распознавания жеста на последнем шаге решает, что эта мультисенсорная последовательность, которую это анализировало, не является своим жестом. Это устанавливает свое состояние в UIGestureRecognizerStateFailed. Тогда окно отправляет два сенсорных объекта в Законченной фазе к присоединенному представлению в a touchesEnded:withEvent: сообщение.

Устройство распознавания жеста для непрерывного жеста следует за подобной последовательностью, за исключением того, что оно, более вероятно, распознает свой жест, прежде чем сенсорные объекты достигнут Законченной фазы. После распознавания его жеста это устанавливает свое состояние в UIGestureRecognizerStateBegan (не Распознанный). Окно отправляет все последующие сенсорные объекты в мультисенсорной последовательности к устройству распознавания жеста, но не к присоединенному представлению.

Влияние на поставку касаний к представлениям

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

  • delaysTouchesBegan (значение по умолчанию NO) — Обычно, окно представляет сенсорные объекты Начинание и Перемещенные фазы к представлению и устройству распознавания жеста. Установка delaysTouchesBegan к YES препятствует тому, чтобы окно поставило сенсорные объекты в, Начал фазу к представлению. Это гарантирует, что, когда устройство распознавания жеста распознает свой жест, никакая часть сенсорного события не была поставлена присоединенному представлению. Будьте осторожны при установке этого свойства, потому что оно может сделать интерфейсное чувство безразличным.

    Эта установка обеспечивает подобное поведение для delaysContentTouches свойство на UIScrollView; в этом случае, когда прокрутка начинается вскоре после того, как касание начинается, подпредставления объекта представления прокрутки никогда не получают касание, таким образом, нет никакой флэш-памяти визуальной обратной связи.

  • delaysTouchesEnded (значение по умолчанию YES) — Когда это свойство установлено вYES, это гарантирует, что представление не завершает действие, которое жест мог бы хотеть отменить позже. Когда устройство распознавания жеста анализирует сенсорное событие, окно не поставляет сенсорные объекты в Законченной фазе к присоединенному представлению. Если устройство распознавания жеста распознает свой жест, сенсорные объекты отменяются. Если устройство распознавания жеста не распознает свой жест, окно поставляет эти объекты представлению через a touchesEnded:withEvent: сообщение. Установка этого свойства к NO позволяет представлению анализировать сенсорные объекты в Законченной фазе в то же время, что и устройство распознавания жеста.

    Полагайте, например, что представление имеет устройство распознавания жеста касания, требующее двух касаний и пользователя двойные касания представление. С набором свойств к YES, представление добирается touchesBegan:withEvent:, touchesBegan:withEvent:, touchesCancelled:withEvent:, и touchesCancelled:withEvent:. Если это свойство установлено в NO, представление получает следующую последовательность сообщений: touchesBegan:withEvent:, touchesEnded:withEvent:, touchesBegan:withEvent:, и touchesCancelled:withEvent:, что означает это в touchesBegan:withEvent:, представление может распознать двойное касание.

Если устройство распознавания жеста обнаруживает касание, которое оно определяет, не часть его жеста, оно может передать касание непосредственно его представлению. Сделать это, вызовы устройства распознавания жеста ignoreTouch:forEvent: на себе, передающий в сенсорном объекте.

Создание пользовательского устройства распознавания жеста

Для реализации пользовательского устройства распознавания жеста сначала создайте подкласс UIGestureRecognizer в XCode. Затем добавьте следующий import директива в заголовочном файле Вашего подкласса:

#import <UIKit/UIGestureRecognizerSubclass.h>

Затем, скопируйте следующие объявления метода с UIGestureRecognizerSubclass.h к Вашему заголовочному файлу; это методы, которые Вы переопределяете в своем подклассе:

- (void)reset;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

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

Заметьте что состояние свойство в UIGestureRecognizerSubclass.h теперь readwrite вместо readonly, поскольку это находится в UIGestureRecognizer.h. Ваш подкласс изменяет свое состояние путем присвоения UIGestureRecognizerState константы к тому свойству.

Реализация методов Сенсорной Обработки событий для пользовательского устройства распознавания жеста

Основа реализации для пользовательского устройства распознавания жеста является этими четырьмя методами: touchesBegan:withEvent:, touchesMoved:withEvent:, touchesEnded:withEvent:, и touchesCancelled:withEvent:. В этих методах Вы переводите низкоуровневые сенсорные события в распознавание жеста путем установки состояния устройства распознавания жеста. Перечисление 1-8 создает устройство распознавания жеста для дискретного одно-сенсорного жеста галочки. Это записывает среднюю точку жеста — точка, в которой черта вверх начинается — так, чтобы клиенты могли получить это значение.

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

  Реализация перечисления 1-8 устройства распознавания жеста галочки

#import <UIKit/UIGestureRecognizerSubclass.h>
 
// Implemented in your custom subclass
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    if ([touches count] != 1) {
        self.state = UIGestureRecognizerStateFailed;
        return;
    }
}
 
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    if (self.state == UIGestureRecognizerStateFailed) return;
    UIWindow *win = [self.view window];
    CGPoint nowPoint = [touches.anyObject locationInView:win];
    CGPoint nowPoint = [touches.anyObject locationInView:self.view];
    CGPoint prevPoint = [touches.anyObject previousLocationInView:self.view];
 
    // strokeUp is a property
    if (!self.strokeUp) {
        // On downstroke, both x and y increase in positive direction
        if (nowPoint.x >= prevPoint.x && nowPoint.y >= prevPoint.y) {
            self.midPoint = nowPoint;
            // Upstroke has increasing x value but decreasing y value
        } else if (nowPoint.x >= prevPoint.x && nowPoint.y <= prevPoint.y) {
            self.strokeUp = YES;
        } else {
            self.state = UIGestureRecognizerStateFailed;
        }
    }
}
 
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    if ((self.state == UIGestureRecognizerStatePossible) && self.strokeUp) {
        self.state = UIGestureRecognizerStateRecognized;
    }
}
 
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesCancelled:touches withEvent:event];
    self.midPoint = CGPointZero;
    self.strokeUp = NO;
    self.state = UIGestureRecognizerStateFailed;
}

Изменения состояния для дискретных и непрерывных жестов отличаются, как описано в Жесте, которым Устройства распознавания Управляют в Конечном автомате. При создании пользовательского устройства распознавания жеста Вы указываете, дискретно ли это или непрерывно путем присвоения его соответствующие состояния. Как пример, устройство распознавания жеста галочки в Перечислении 1-8 никогда не устанавливает состояние в, Начался или Измененный, потому что это дискретно.

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

Для больше о создании пользовательских устройств распознавания жеста, см. 2012 WWDC: Создание Усовершенствованных Устройств распознавания Жеста.

Сброс состояния устройства распознавания жеста

Если Ваши переходы устройства распознавания жеста к Распознали/Закончили, Отмененный, или Неработающий, UIGestureRecognizer класс вызывает reset метод как раз перед переходами устройства распознавания жеста назад к Возможному.

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

Перечисление 1-9  , Сбрасывающее устройство распознавания жеста

- (void)reset {
    [super reset];
    self.midPoint = CGPointZero;
    self.strokeUp = NO;
}