Установка направления для UISwipeGestureRecognizer

132

Я хочу добавить простое распознавание жестов смахивания в свой проект iPhone на основе просмотра. Следует распознавать жесты во всех направлениях (вправо, вниз, влево, вверх).

В документации для UISwipeGestureRecognizer указано:

Вы можете указать несколько направлений, указав несколько констант UISwipeGestureRecognizerDirection с помощью операндов побитового ИЛИ. Направление по умолчанию - UISwipeGestureRecognizerDirectionRight.

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

- (void)viewDidLoad {
    UISwipeGestureRecognizer *recognizer;

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionUp)];
    [[self view] addGestureRecognizer:recognizer];
    [recognizer release]; 
    [super viewDidLoad];
}

-(void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {
    NSLog(@"Swipe received.");
}

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

- (void)viewDidLoad {
    UISwipeGestureRecognizer *recognizer;

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
    [[self view] addGestureRecognizer:recognizer];
    [recognizer release];

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionUp)];
    [[self view] addGestureRecognizer:recognizer];
    [recognizer release];

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionDown)];
    [[self view] addGestureRecognizer:recognizer];
    [recognizer release];

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)];
    [[self view] addGestureRecognizer:recognizer];
    [recognizer release];

    [super viewDidLoad];
}

-(void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {
    NSLog(@"Swipe received.");
}
sandisn
источник
3
это совершенно не связано, но [super viewDidLoad]; должно быть первым заявлением в - (void) viewDidLoad
Михир Мехта

Ответы:

115

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

Это означает, что проверка фактического направления всегда будет неудачной, если разрешено более одного направления. Вы можете легко убедиться в этом, если выведите значение 'direction' в методе селектора (т.е.-(void)scrollViewSwiped:(UISwipeGestureRecognizer *)recognizer ).

Отправил отчет об ошибке (№ 8276386) в Apple.

[Обновление] Я получил ответ от Apple, в котором говорится, что поведение работает так, как задумано.

Так, например, в табличном представлении вы можете провести пальцем влево или вправо в ячейке табличного представления, чтобы вызвать `` удаление '' (при этом направления жеста смахивания будут установлены влево и вправо)

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

RupertP
источник
35
Я готов поспорить, что почти каждый, кто впервые использует распознаватель жестов, делает точно такое же неверное предположение о том, как должно работать свойство direction.
memmons
Глупо создавать 4 разных распознавателя для отслеживания движений вверх, вниз, влево и вправо, но вот и все.
memmons
вау, это отстой, не так уж и много, но похоже, что они могли бы добавить что-то, что они могли бы добавить
marchinram
2
В их заголовочном файле написано: @property (nonatomic) UISwipeGestureRecognizerDirection direction; // по умолчанию - UISwipeGestureRecognizerDirectionRight. желаемое направление смахивания. может быть указано несколько направлений
nicktmro
1
Согласился, что это кажется странной реализацией со стороны Apple. У вас должна быть возможность указать несколько направлений, а затем проверить одно из них.
ChrisP 07
25

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

Lars
источник
Это правильное решение. 2 GR, по одному для вверх и вниз / по одному для левого и правого. Бинго!
logancautrell
22

Ну, это отстой, я решил проблему, добавив 2 жеста, как упоминал Ларс, и они отлично сработали ...

1) влево / вправо 2) вверх / вниз

  

UISwipeGestureRecognizer *swipeLeftRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
    [swipeLeftRight setDirection:(UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionLeft )];
    [self.view addGestureRecognizer:swipeLeftRight];

    UISwipeGestureRecognizer *swipeUpDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
    [swipeUpDown setDirection:(UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown )];
    [self.view addGestureRecognizer:swipeUpDown];
yunas
источник
13
UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(didSwipe:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[self.view addGestureRecognizer:recognizer];
[recognizer release];

recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(didSwipe:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[self.view addGestureRecognizer:recognizer];
[recognizer release];

Теперь это функция didSwipe

- (void) didSwipe:(UISwipeGestureRecognizer *)recognizer{
      if([recognizer direction] == UISwipeGestureRecognizerDirectionLeft){
          //Swipe from right to left
          //Do your functions here
      }else{
          //Swipe from left to right
          //Do your functions here
      }
 }
KarenAnne
источник
5

Если вы используете Xcode 4.2, вы можете добавить распознаватели жестов @ раскадровку, а затем связать распознаватели жестов GUI с IBActions.

Вы можете найти распознаватели жестов в библиотеке объектов на панели служебных программ (внизу правой панели).

Затем нужно просто перетащить Control до соответствующего действия.

Grymm
источник
5

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

Вот почему : тот же экземпляр UISwipeGestureRecognizer, который вы создаете, является экземпляром, который передается селектору в качестве отправителя. Поэтому, если вы установите его для распознавания всех четырех направлений, он вернет true дляsgr.direction == xxx где xxx - любое из четырех направлений.

Вот альтернативный обходной путь, который требует меньше кода (предполагает использование ARC):

for(int d = UISwipeGestureRecognizerDirectionRight; d <= UISwipeGestureRecognizerDirectionDown; d = d*2) {
    UISwipeGestureRecognizer *sgr = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    sgr.direction = d;
    [self.view addGestureRecognizer:sgr];
}
tybro0103
источник
2

Вот пример кода для использования UISwipeGestureRecognizer. Обратите внимание на комментарии.

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //add gesture recognizer. The 'direction' property of UISwipeGestureRecognizer only sets the allowable directions. It does not return to the user the direction that was actaully swiped. Must set up separate gesture recognizers to handle the specific directions for which I want an outcome.
    UISwipeGestureRecognizer *gestureRight;
    UISwipeGestureRecognizer *gestureLeft;
    gestureRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRight:)];//direction is set by default.
    gestureLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeft:)];//need to set direction.
    [gestureLeft setDirection:(UISwipeGestureRecognizerDirectionLeft)];
    //[gesture setNumberOfTouchesRequired:1];//default is 1
    [[self view] addGestureRecognizer:gestureRight];//this gets things rolling.
    [[self view] addGestureRecognizer:gestureLeft];//this gets things rolling.
}

swipeRight и swipeLeft - это методы, которые вы используете для выполнения определенных действий, основанных на смахивании влево или вправо. Например:

- (void)swipeRight:(UISwipeGestureRecognizer *)gesture
{
    NSLog(@"Right Swipe received.");//Lets you know this method was called by gesture recognizer.
    NSLog(@"Direction is: %i", gesture.direction);//Lets you know the numeric value of the gesture direction for confirmation (1=right).
    //only interested in gesture if gesture state == changed or ended (From Paul Hegarty @ standford U
    if ((gesture.state == UIGestureRecognizerStateChanged) ||
    (gesture.state == UIGestureRecognizerStateEnded)) {

    //do something for a right swipe gesture.
    }
}
Greg
источник
2
UISwipeGestureRecognizer *Updown=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleGestureNext:)];
            Updown.delegate=self;
            [Updown setDirection:UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp];
            [overLayView addGestureRecognizer:Updown];

            UISwipeGestureRecognizer *LeftRight=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleGestureNext:)];
            LeftRight.delegate=self;
            [LeftRight setDirection:UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight];
            [overLayView addGestureRecognizer:LeftRight];
            overLayView.userInteractionEnabled=NO;


    -(void)handleGestureNext:(UISwipeGestureRecognizer *)recognizer
    {
        NSLog(@"Swipe Recevied");
        //Left
        //Right
        //Top
        //Bottom
    }
bhavik
источник
2

Swift 2.1

Мне пришлось использовать следующие

    for var x in [
        UISwipeGestureRecognizerDirection.Left,
        UISwipeGestureRecognizerDirection.Right,
        UISwipeGestureRecognizerDirection.Up,
        UISwipeGestureRecognizerDirection.Down
    ] {
        let r = UISwipeGestureRecognizer(target: self, action: "swipe:")
        r.direction = x
        self.view.addGestureRecognizer(r)
    }
Андрей
источник
1

хм, странно, у меня работает идеально, я делаю то же самое

думаю, тебе стоит попробовать посмотреть на

UIGestureRecognizerDelegate метод

- (BOOL)gestureRecognizerShouldBegin:(UISwipeGestureRecognizer *)gestureRecognizer {
   // also try to look what's wrong with gesture
   NSLog(@"should began gesture %@", gestureRecognizer);
   return YES;
}

в логах вы должны увидеть что-то вроде:

должен начаться жест; target = <(действие = actionForUpDownSwipeGestureRecognizer :, target =)>; направление = вверх, вниз, влево, вправо>

iFreeman
источник
Что не работает? gestureRecognizerShouldBegin: отлично работает.
Даньял Айтекин
1

используйте это, это должна быть битовая операция

   gesture.direction & UISwipeGestureRecognizerDirectionUp || 
   gesture.direction & UISwipeGestureRecognizerDirectionDown
Уильям Ву
источник
0

Это сводило меня с ума. Наконец-то я нашел надежный способ иметь несколько swipeGestureRecognizers.

Похоже, что в iOS есть ошибка, если имя вашего селектора «действия» одинаково для нескольких swipeGestureRecognizers. Если вы просто назовете их по-другому, например handleLeftSwipeFrom и handleRightSwipeFrom, все заработает.

UISwipeGestureRecognizer *recognizer;

recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleLeftSwipeFrom:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[[self view] addGestureRecognizer:recognizer];
[recognizer release];

recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleRightSwipeFrom:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[[self view] addGestureRecognizer:recognizer];
[recognizer release];
Alex
источник