Impostazione della direzione per UISwipeGestureRecognizer


132

Voglio aggiungere il semplice riconoscimento dei gesti di scorrimento al mio progetto iPhone basato sulla vista. I gesti in tutte le direzioni (destra, giù, sinistra, su) dovrebbero essere riconosciuti.

È indicato nei documenti per UISwipeGestureRecognizer:

È possibile specificare più direzioni specificando più costanti UISwipeGestureRecognizerDirection utilizzando operandi OR bit a bit. La direzione predefinita è UISwipeGestureRecognizerDirectionRight.

Tuttavia per me non funziona. Quando tutte e quattro le direzioni sono OR, vengono riconosciuti solo i movimenti sinistro e destro.

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

Ho risolto questo problema aggiungendo quattro riconoscimenti alla vista ma sono curioso di sapere perché non ha funzionato come pubblicizzato nei documenti?

- (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
è del tutto indipendente, ma [super viewDidLoad]; dovrebbe essere la prima affermazione in - (void) viewDidLoad
Mihir Mehta

Risposte:


115

Sembra che ci sia un bug. Puoi specificare la direzione o le direzioni consentite come hai fatto. Ma quando si tenta di accedere alla direzione effettiva che ha attivato il colpo nel metodo del selettore di azioni, si ottiene comunque la maschera di bit impostata originariamente (per le direzioni consentite).

Ciò significa che i controlli per la direzione effettiva falliranno sempre quando è consentita più di 1 direzione. Puoi vederlo da solo abbastanza facilmente quando emetti il ​​valore di 'direction' nel metodo selector (cioè -(void)scrollViewSwiped:(UISwipeGestureRecognizer *)recognizer).

Ha presentato una segnalazione di bug (n. 8276386) ad Apple.

[Aggiornamento] Ho ricevuto una risposta da Apple dicendo che il comportamento funziona come previsto.

Ad esempio, in una vista tabella è possibile scorrere verso sinistra o verso destra in una cella della vista tabella per attivare "Elimina" (questo avrebbe le direzioni del gesto di scorrimento impostato su sinistra e destra)

Ciò significa che la soluzione originale è il modo in cui dovrebbe essere utilizzata. La proprietà direction può essere utilizzata solo per riconoscere correttamente i gesti, ma non nel metodo eseguito su un riconoscimento riuscito per confrontare la direzione effettiva che ha attivato il riconoscimento.


35
Sono disposto a scommettere che quasi tutti quelli che usano per primi il riconoscimento dei gesti di scorrimento fanno esattamente la stessa errata ipotesi su come dovrebbe funzionare la proprietà direction.
Memmons,

È sciocco dover creare 4 diversi riconoscitori per rintracciare i passaggi verso l'alto, il basso, a sinistra ea destra, ma eccoti qui.
Memmons,

wow che fa schifo, non un grosso problema ma sembra qualcosa che avrebbero potuto aggiungere
marchinram,

2
Il loro file di intestazione dice: @property (nonatomic) UISwipeGestureRecognizerDirection direction; // l'impostazione predefinita è UISwipeGestureRecognizerDirectionRight. la direzione desiderata del colpo. è possibile specificare più direzioni
nicktmro

1
Concordato sul fatto che questa sembra una strana implementazione da parte di Apple. Dovresti essere in grado di specificare più direzioni e quindi testare una di quelle direzioni.
ChrisP

25

Ho notato che i gesti sinistra / destra e su / giù funzionano insieme in coppia, quindi devi solo specificare due riconoscimenti gestuali. E i documenti sembrano essere sbagliati.


Questa è la soluzione corretta 2 GR, uno per su e giù / uno per sinistra e destra. Bingo!
logancautrell,

22

Bene, fa schifo, ho risolto il problema aggiungendo 2 gesti come indicato da Lars e che ha funzionato perfettamente ...

1) Sinistra / Destra 2) Su / Giù

  

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

Ora questa è la funzione 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

Se si utilizza Xcode 4.2 è possibile aggiungere Gesture Recognizer @ allo storyboard e quindi collegare i riconoscimenti dei gesti della GUI a IBActions.

È possibile trovare i Riconoscitori di gesti nella Libreria oggetti del riquadro Utilità (La parte inferiore del riquadro destro).

Quindi si tratta solo di trascinare il controllo sull'azione appropriata.


5

Se vuoi che rilevi tutte e quattro le direzioni, dovrai creare quattro istanze, come hai fatto nel tuo aggirare.

Ecco perché : la stessa istanza di UISwipeGestureRecognizer che crei è l'istanza che viene passata al selettore come mittente. Quindi, se lo imposti per riconoscere tutte e quattro le direzioni, tornerà vero per sgr.direction == xxxdove xxx è una delle quattro direzioni.

Ecco una soluzione alternativa che comporta meno codice (presuppone l'utilizzo di 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

Ecco un esempio di codice per l'utilizzo di UISwipeGestureRecognizer. Nota commenti.

- (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 e swipeLeft sono metodi utilizzati per eseguire attività specifiche in base allo scorrimento sinistro o destro. Per esempio:

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

Ho dovuto usare il seguente

    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, strano, funziona perfettamente per me, faccio esattamente la stessa cosa

pensa che dovresti provare a guardare

Metodo UIGestureRecognizerDelegate

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

nei registri devi vedere qualcosa come:

dovrebbe iniziare il gesto; target = <(action = actionForUpDownSwipeGestureRecognizer :, target =)>; direzione = su, giù, sinistra, destra>


Cosa non funziona? gestureRecognizerShouldBegin: funziona benissimo.
Danyal Aytekin,

1

usare questo, dovrebbe essere l'operazione di bit

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

0

Questo mi stava facendo impazzire. Alla fine ho trovato un modo affidabile per avere più swipeGestureRecognizers.

Sembra che ci sia un bug in iOS se il nome del selettore "azione" è lo stesso su più swipeGestureRecognizer. Se li nominate in modo diverso, ad esempio handleLeftSwipeFrom e handleRightSwipeFrom, tutto funziona.

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];
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.