Définition de la direction pour UISwipeGestureRecognizer


132

Je souhaite ajouter une reconnaissance gestuelle simple à mon projet iPhone basé sur la vue. Les gestes dans toutes les directions (droite, bas, gauche, haut) doivent être reconnus.

Il est indiqué dans la documentation pour UISwipeGestureRecognizer:

Vous pouvez spécifier plusieurs directions en spécifiant plusieurs constantes UISwipeGestureRecognizerDirection à l'aide d'opérandes OR au niveau du bit. La direction par défaut est UISwipeGestureRecognizerDirectionRight.

Cependant pour moi cela ne fonctionne pas. Lorsque les quatre directions sont marquées par OU, seuls les balayages vers la gauche et vers la droite sont reconnus.

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

J'ai résolu ce problème en ajoutant quatre outils de reconnaissance à la vue, mais je suis curieux de savoir pourquoi cela n'a pas fonctionné comme annoncé dans la documentation?

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

3
il est totalement indépendant, mais [super viewDidLoad]; devrait être la première déclaration dans - (void) viewDidLoad
Mihir Mehta

Réponses:


115

On dirait qu'il y a un bug. Vous pouvez spécifier la ou les directions autorisées comme vous l'avez fait. Mais lorsque vous essayez d'accéder à la direction réelle qui a déclenché le balayage dans la méthode du sélecteur d'action, vous obtenez toujours le masque de bits que vous avez initialement défini (pour les directions autorisées).

Cela signifie que les vérifications de la direction réelle échoueront toujours lorsque plus d'une direction est autorisée. Vous pouvez le voir par vous-même assez facilement lorsque vous indiquez la valeur de «direction» dans la méthode de sélection (ie -(void)scrollViewSwiped:(UISwipeGestureRecognizer *)recognizer).

A déposé un rapport de bogue (# 8276386) à Apple.

[Mise à jour] J'ai reçu une réponse d'Apple disant que le comportement fonctionne comme prévu.

Ainsi, par exemple, dans une vue de tableau, vous pouvez balayer vers la gauche ou la droite dans une cellule de vue de tableau pour déclencher la `` suppression '' (cela aurait des directions du geste de balayage définies à gauche et à droite)

Cela signifie que la solution de contournement d'origine est la manière dont elle est censée être utilisée. La propriété direction ne peut être utilisée que pour faire reconnaître correctement les gestes, mais pas dans la méthode effectuée sur une reconnaissance réussie pour comparer la direction réelle qui a déclenché la reconnaissance.


35
Je suis prêt à parier que presque tous ceux qui utilisent en premier le logiciel de reconnaissance de geste de balayage font exactement la même hypothèse incorrecte sur le fonctionnement de la propriété de direction.
memmons

C'est idiot d'avoir à créer 4 outils de reconnaissance différents pour suivre les balayages vers le haut, le bas, la gauche et la droite, mais vous y êtes.
memmons

wow ça craint un peu, pas une grosse affaire mais semble être quelque chose qu'ils auraient pu ajouter
marchinram

2
Leur fichier d'en-tête dit: @property (nonatomic) UISwipeGestureRecognizerDirection direction; // La valeur par défaut est UISwipeGestureRecognizerDirectionRight. la direction souhaitée du balayage. plusieurs directions peuvent être spécifiées
nicktmro

1
Convenu que cela semble être une implémentation étrange de la part d'Apple. Vous devriez être en mesure de spécifier plusieurs directions, puis de tester l'une de ces directions.
ChrisP

25

J'ai remarqué que les gestes gauche / droite et haut / bas fonctionnent ensemble par paires, il vous suffit donc de spécifier deux outils de reconnaissance de gestes. Et les documents semblent être faux.


C'est la bonne solution. 2 GR, un pour le haut et le bas / un pour la gauche et la droite. Bingo!
logancautrell

22

Eh bien ça craint, j'ai résolu le problème en ajoutant 2 gestes comme Lars l'a mentionné et cela a parfaitement fonctionné ...

1) Gauche / Droite 2) Haut / Bas

  

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

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

Voici maintenant la fonction 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
      }
 }

5

Si vous utilisez Xcode 4.2, vous pouvez ajouter des Gesture Recognizers @ le storyboard, puis lier les Gesture Recognizers GUI à IBActions.

Vous pouvez trouver les outils de reconnaissance de gestes dans la bibliothèque d'objets du volet Utilitaires (en bas du volet droit).

Ensuite, c'est juste une question de contrôle-glisser vers l'action appropriée.


5

Si vous souhaitez qu'il détecte les quatre directions, vous devrez créer quatre instances, comme vous l'avez fait dans votre solution de contournement.

Voici pourquoi : La même instance de UISwipeGestureRecognizer que vous créez est l'instance qui est transmise au sélecteur en tant qu'expéditeur. Donc, si vous le définissez pour reconnaître les quatre directions, il retournera true pour sgr.direction == xxxoù xxx est l'une des quatre directions.

Voici une solution alternative qui implique moins de code (suppose l'utilisation d'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];
}

2

Voici un exemple de code pour l'utilisation d'UISwipeGestureRecognizer. Notez les commentaires.

- (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 et swipeLeft sont des méthodes que vous utilisez pour effectuer des activités spécifiques basées sur un balayage vers la gauche ou vers la droite. Par exemple:

- (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.
    }
}

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
    }

2

Swift 2.1

J'ai dû utiliser ce qui suit

    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

hmm, étrange, ça marche parfaitement pour moi, je fais exactement la même chose

pense que tu devrais essayer de regarder

Méthode UIGestureRecognizerDelegate

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

dans les journaux, vous devez voir quelque chose comme:

devrait commencer le geste; target = <(action = actionForUpDownSwipeGestureRecognizer :, target =)>; direction = haut, bas, gauche, droite>


Qu'est-ce qui ne marche pas? gestureRecognizerShouldBegin: fonctionne très bien.
Danyal Aytekin

1

utilisez ceci, cela devrait être l'opération de bit

   gesture.direction & UISwipeGestureRecognizerDirectionUp || 
   gesture.direction & UISwipeGestureRecognizerDirectionDown

0

Cela me rendait fou. J'ai finalement trouvé un moyen fiable d'avoir plusieurs swipeGestureRecognizers.

Il semble qu'il y ait un bogue dans iOS si le nom de votre sélecteur "action" est le même sur plusieurs swipeGestureRecognizers. Si vous les nommez différemment, par exemple handleLeftSwipeFrom et handleRightSwipeFrom, tout fonctionne.

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];
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.