Как распознать пролистывание во всех 4 направлениях? - PullRequest
26 голосов
/ 18 ноября 2011

Мне нужно распознавать пролистывания во всех направлениях ( Вверх / Вниз / Влево / Вправо ). Не одновременно, но мне нужно их узнать.

Я пытался:

  UISwipeGestureRecognizer *Swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(SwipeRecognizer:)];
  Swipe.direction = (UISwipeGestureRecognizerDirectionLeft | 
                     UISwipeGestureRecognizerDirectionRight |
                     UISwipeGestureRecognizerDirectionDown | 
                     UISwipeGestureRecognizerDirectionUp);
  [self.view addGestureRecognizer:Swipe];
  [Swipe release];

но ничего не появилось на SwipeRecognizer

Вот код для SwipeRecognizer:

- (void) SwipeRecognizer:(UISwipeGestureRecognizer *)sender {
  if ( sender.direction == UISwipeGestureRecognizerDirectionLeft )
    NSLog(@" *** SWIPE LEFT ***");
  if ( sender.direction == UISwipeGestureRecognizerDirectionRight )
    NSLog(@" *** SWIPE RIGHT ***");
  if ( sender.direction == UISwipeGestureRecognizerDirectionDown )
    NSLog(@" *** SWIPE DOWN ***");
  if ( sender.direction == UISwipeGestureRecognizerDirectionUp )
    NSLog(@" *** SWIPE UP ***");
}

Как я могу это сделать? Как можно назначить моему объекту Swipe все разные направления?

Ответы [ 8 ]

21 голосов
/ 18 ноября 2011

Вы устанавливаете направление следующим образом

  UISwipeGestureRecognizer *Swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(SwipeRecognizer:)];
  Swipe.direction = (UISwipeGestureRecognizerDirectionLeft | 
                     UISwipeGestureRecognizerDirectionRight |
                     UISwipeGestureRecognizerDirectionDown | 
                     UISwipeGestureRecognizerDirectionUp);

Это направление будет таким, когда вы получите обратный вызов, поэтому нормально, что все ваши тесты не пройдены.Если бы у вас было

- (void) SwipeRecognizer:(UISwipeGestureRecognizer *)sender {
  if ( sender.direction | UISwipeGestureRecognizerDirectionLeft )
    NSLog(@" *** SWIPE LEFT ***");
  if ( sender.direction | UISwipeGestureRecognizerDirectionRight )
    NSLog(@" *** SWIPE RIGHT ***");
  if ( sender.direction | UISwipeGestureRecognizerDirectionDown )
    NSLog(@" *** SWIPE DOWN ***");
  if ( sender.direction | UISwipeGestureRecognizerDirectionUp )
    NSLog(@" *** SWIPE UP ***");
}

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


РЕДАКТИРОВАТЬ

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

4 голосов
/ 13 ноября 2013

Я действительно столкнулся с этой проблемой раньше.В итоге я создал подкласс UIView, переопределив touchesMoved: и выполняя некоторые математические расчеты для вычисления направления.

Вот общая идея:

#import "OmnidirectionalControl.h"

typedef NS_ENUM(NSInteger, direction) {
    Down = 0, DownRight = 1,
    Right = 2, UpRight = 3,
    Up = 4, UpLeft = 5,
    Left = 6, DownLeft = 7
};

@interface OmnidirectionalControl ()

@property (nonatomic) CGPoint startTouch;
@property (nonatomic) CGPoint endTouch;

@end

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    self.startTouch = [[touches allObjects][0] locationInView:self];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    self.lastTouch = [[[touches allObjects] lastObject] locationInView:self];
    NSLog(@"Direction: %d", [self calculateDirectionFromTouches]);
}

-(direction)calculateDirectionFromTouches {
    NSInteger xDisplacement = self.lastTouch.x-self.startTouch.x;
    NSInteger yDisplacement = self.lastTouch.y-self.startTouch.y;

    float angle = atan2(xDisplacement, yDisplacement);
    int octant = (int)(round(8 * angle / (2 * M_PI) + 8)) % 8;

    return (direction) octant;
}

Для простоты в touchesMoved:, Я только регистрирую направление, но вы можете делать с этой информацией все, что хотите (например, передавать ее делегату, публиковать уведомления и т. Д.).В touchesMoved вам также понадобится какой-нибудь метод, чтобы определить, закончено ли свайп или нет, но это не совсем относится к вопросу, поэтому я оставлю это вам.Математика в calculateDirectionFromTouches объясняется здесь .

4 голосов
/ 29 мая 2013

К сожалению, вы не можете использовать direction свойство для прослушивания распознавателя; это только дает вам обнаруженные направления распознавателем. Я использовал два разных UISwipeGestureRecognizer с этой целью, смотрите мой ответ здесь: https://stackoverflow.com/a/16810160/936957

2 голосов
/ 23 декабря 2013

Я наконец нашел самый простой ответ, пожалуйста, пометьте его как ответ, если вы согласны.

Если у вас есть только одно направление свайп + панорамирование, вы просто говорите: [myPanRecogznier requireGestureRecognizerToFail: mySwipeRecognizer];

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

Например, если вы хотите распознать 2 пролистывания (левый и правый), а также хотите разрешить пользователю перемещаться вверх, вы определяете распознаватели жестов как свойства или переменные экземпляра, а затем устанавливаете свой VCв качестве делегата в распознавателе жестов панорамирования:

_swipeLeft = [[UISwipeGestureRecognizer alloc] ...]; // use proper init here
_swipeRight = [[UISwipeGestureRecognizer alloc] ...]; // user proper init here
_swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
_swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
_pan = [[UIPanGestureRecognizer alloc] ...]; // use proper init here

_pan.delegate = self;

// then add recognizers to your view

Затем вы реализуете - (BOOL) gestRecognizer: (UIGestureRecognizer *)*

Это говорит о том, что распознаватель жестов панорамирования работает только в том случае, если не удается распознать как левые, так и правые пролистывания - идеально!

Надеемся, что в будущем Apple просто разрешит нам передать массив в requireGestureRecognizerToFail: метод.

1 голос
/ 05 июня 2014

Вы можете добавить только одну диагональ с помощью SwipeGesture, затем ...

    UISwipeGestureRecognizer *swipeV = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(action)];
    UISwipeGestureRecognizer *swipeH = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(action)];
    swipeH.direction = ( UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight  );
    swipeV.direction = ( UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown );
    [self addGestureRecognizer:swipeH];
    [self addGestureRecognizer:swipeV];
     self.userInteractionEnabled = YES;
0 голосов
/ 13 июня 2015

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

В методе viewDidLoad просто укажите требуемый UISwipeGestureRecognizer:

- (void)viewDidLoad{
    UISwipeGestureRecognizer *recognizerUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeUp:)];
    recognizerUp.direction = UISwipeGestureRecognizerDirectionUp;
    [[self view] addGestureRecognizer:recognizerUp];

    UISwipeGestureRecognizer *recognizerDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeDown:)];
    recognizerDown.direction =  UISwipeGestureRecognizerDirectionDown;
    [[self view] addGestureRecognizer:recognizerDown];
}

Затем просто реализуйте соответствующие методы обработки свайпов:

- (void)handleSwipeUp:(UISwipeGestureRecognizer *)sender{
    if (sender.state == UIGestureRecognizerStateEnded){
        NSLog(@"SWIPE UP");
    }
}


- (void)handleSwipeDown:(UISwipeGestureRecognizer *)sender{
    if (sender.state == UIGestureRecognizerStateEnded){
        NSLog(@"SWIPE DOWN");
    }
}
0 голосов
/ 22 сентября 2014
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");
}
0 голосов
/ 28 января 2013

Используйте UIPanGestureRecogizer и определите направления движения, которые вас интересуют. подробности смотрите в документации к UIPanGestureRecognizer. -rrh

// add pan recognizer to the view when initialized
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panRecognized:)];
[panRecognizer setDelegate:self];
[self addGestureRecognizer:panRecognizer]; // add to the view you want to detect swipe on


-(void)panRecognized:(UIPanGestureRecognizer *)sender
{
    if (sender.state == UIGestureRecognizerStateBegan) {
        // you might want to do something at the start of the pan
    }

    CGPoint distance = [sender translationInView:self]; // get distance of pan/swipe in the view in which the gesture recognizer was added
    CGPoint velocity = [sender velocityInView:self]; // get velocity of pan/swipe in the view in which the gesture recognizer was added
    float usersSwipeSpeed = abs(velocity.x); // use this if you need to move an object at a speed that matches the users swipe speed
    NSLog(@"swipe speed:%f", usersSwipeSpeed);
    if (sender.state == UIGestureRecognizerStateEnded) {
        [sender cancelsTouchesInView]; // you may or may not need this - check documentation if unsure
        if (distance.x > 0) { // right
            NSLog(@"user swiped right");
        } else if (distance.x < 0) { //left
            NSLog(@"user swiped left");
        }
        if (distance.y > 0) { // down
            NSLog(@"user swiped down");
        } else if (distance.y < 0) { //up
            NSLog(@"user swiped up");
        }
        // Note: if you don't want both axis directions to be triggered (i.e. up and right) you can add a tolerence instead of checking the distance against 0 you could check for greater and less than 50 or 100, etc.
    }
}

ИЗМЕНЕНИЕ В ГОСУДАРСТВЕННОМ КОДЕКСЕ С ЭТИМ

// если ВЫ ХОТИТЕ ТОЛЬКО ОДНО ОДНОРАСНОЕ СКОРОСТЬ ВВЕРХ, ВНИЗ, ВЛЕВО И ПРАВО *

if (sender.state == UIGestureRecognizerStateEnded) {
        [sender cancelsTouchesInView]; // you may or may not need this - check documentation if unsure
        if (distance.x > 0 && abs(distance.x)>abs(distance.y)) { // right
            NSLog(@"user swiped right");
        } else if (distance.x < 0 && abs(distance.x)>abs(distance.y)) { //left
            NSLog(@"user swiped left");
        }
        if (distance.y > 0 && abs(distance.y)>abs(distance.x)) { // down
            NSLog(@"user swiped down");
        } else if (distance.y < 0 && abs(distance.y)>abs(distance.x)) { //up
            NSLog(@"user swiped up");
        }

    } 
...