web-dev-qa-db-fra.com

Comment reconnaître le glissement dans les 4 directions?

Je dois reconnaître les balayages dans toutes les directions ( Haut/Bas/Gauche/Droite ). Pas simultanément, mais je dois les reconnaître.

J'ai essayé:

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

mais rien n'est apparu sur SwipeRecognizer

Voici le code pour 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 ***");
}

Comment puis-je faire ceci? Comment assigner à mon objet Swipe toutes les directions différentes?

26
elp

Vous définissez la direction comme ça

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

C'est la direction que vous prendrez lorsque vous obtiendrez le rappel. Il est donc normal que tous vos tests échouent. Si tu avais

- (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 ***");
}

Les tests réussiraient (mais ils réussiraient tous pour que vous ne puissiez en tirer aucune information). Si vous souhaitez faire la distinction entre des balayages dans des directions différentes, vous aurez besoin de systèmes de reconnaissance des gestes distincts.


MODIFIER

Comme indiqué dans les commentaires, voir cette réponse . Apparemment, même cela ne fonctionne pas. Vous devez créer un balayage avec une seule direction pour vous rendre la vie plus facile.

21
jbat100

En fait, j'ai rencontré ce problème avant. J'ai fini par créer une sous-classe UIView, en surchargeant touchesMoved: et en effectuant quelques calculs pour calculer la direction.

Voici l'idée générale:

#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;
}

Par souci de simplicité, dans touchesMoved:, je ne consigne que la direction mais vous pouvez faire ce que vous voulez avec cette information (par exemple, transmettez-la à un délégué, envoyez une notification avec, etc.). Dans touchesMoved, vous aurez également besoin d’une méthode pour déterminer si le balayage est terminé ou non, mais ce n’est pas tout à fait pertinent pour la question, je vous laisse donc cette question. Le calcul dans calculateDirectionFromTouches est expliqué ici .

4
pasawaya

Malheureusement, vous ne pouvez pas utiliser la propriété direction pour écouter le programme de reconnaissance; il ne vous donne que les directions détectées par le dispositif de reconnaissance. J'ai utilisé deux UISwipeGestureRecognizers différents à cette fin. Voir ma réponse ici: https://stackoverflow.com/a/16810160/936957

4

J'ai finalement trouvé la réponse la plus simple, cochez cette case si vous êtes d'accord. 

Si vous n'avez qu'un balayage à balayage + panoramique, vous dites simplement: [myPanRecogznier requireGestureRecognizerToFail: mySwipeRecognizer];

Mais si vous avez deux balayages ou plus, vous ne pouvez pas passer un tableau dans cette méthode. Pour cela, vous devez implémenter UIGestureRecognizerDelegate. 

Par exemple, si vous souhaitez reconnaître 2 balayages (gauche et droite) et que vous souhaitez également permettre à l'utilisateur de faire un panoramique, définissez les reconnaisseurs de mouvements en tant que propriétés ou variables d'instance, puis définissez votre VC comme délégué sur la reconnaissance de geste panoramique: 

_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

Vous implémentez ensuite - (BOOL) gestureRecognizer: (UIGestureRecognizer *) gestureRecognizer shouldRequireFailureOfGestureRecognizer: (UIGestureRecognizer *), une autre méthode de délégation, celle-ci: 

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if (gestureRecognizer == _pan && (otherGestureRecognizer == _swipeLeft || otherGestureRecognizer == _swipeRight)) {
        return YES;
    }

    return NO;
}

Cela indique à la reconnaissance de mouvements panoramique de ne fonctionner que si les balayages gauche et droit ne sont pas reconnus - parfait! 

J'espère qu'à l'avenir, Apple nous laissera simplement passer un tableau à la méthode requireGestureRecognizerToFail :.

2
Alex the Ukrainian

Vous pouvez ajouter une seule diagonale par SwipeGesture, puis ...

    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;
1
Damien Romito
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
bhavik

Ce n'est peut-être pas la meilleure solution, mais vous pouvez toujours spécifier un identificateur UISwipeGestureRecognizer différent pour chaque direction de balayage que vous souhaitez détecter.

Dans la méthode viewDidLoad, définissez simplement le UISwipeGestureRecognizer requis:

- (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];
}

Ensuite, implémentez simplement les méthodes respectives pour gérer les balayages:

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


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

Utilisez un UIPanGestureRecogizer et détectez les instructions de balayage qui vous intéressent. consultez la documentation UIPanGestureRecognizer pour plus de détails. -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.
    }
}

CHANHE IN STATEEND CODE AVEC CE

// si vous voulez seulement un seul coup vers le haut, le bas, la gauche et la droite

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");
        }

    } 
0
Richie Hyatt