Configuración de dirección para UISwipeGestureRecognizer

132

Quiero agregar un simple reconocimiento de gestos de deslizamiento a mi proyecto de iPhone basado en la vista. Deben reconocerse los gestos en todas las direcciones (derecha, abajo, izquierda, arriba).

Se indica en los documentos para UISwipeGestureRecognizer:

Puede especificar múltiples direcciones especificando múltiples constantes UISwipeGestureRecognizerDirection utilizando operandos bit-OR. La dirección predeterminada es UISwipeGestureRecognizerDirectionRight.

Sin embargo para mí no funciona. Cuando las cuatro direcciones son OR, solo se reconocen los deslizamientos hacia la izquierda y hacia la derecha.

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

Solucioné esto agregando cuatro reconocedores a la vista, pero tengo curiosidad por saber por qué no funcionó como se anuncia en los documentos.

- (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
fuente
3
no tiene ninguna relación, pero [super viewDidLoad]; debería ser la primera declaración en - (nulo) viewDidLoad
Mihir Mehta

Respuestas:

115

Parece que hay un error. Puede especificar las direcciones permitidas como lo hizo. Pero cuando intenta acceder a la dirección real que activó el deslizamiento en el método del selector de acción, aún obtiene la máscara de bits que configuró originalmente (para las direcciones permitidas).

Esto significa que las comprobaciones de la dirección real siempre fallarán cuando se permita más de 1 dirección. Puede verlo usted mismo con bastante facilidad cuando genera el valor de 'dirección' en el método selector (es decir-(void)scrollViewSwiped:(UISwipeGestureRecognizer *)recognizer ).

Presentó un informe de error (# 8276386) a Apple.

[Actualización] Recibí una respuesta de Apple diciendo que el comportamiento funciona según lo previsto.

Entonces, por ejemplo, en una vista de tabla, puede deslizar hacia la izquierda o hacia la derecha en una celda de vista de tabla para activar 'eliminar' (esto tendría las direcciones del gesto de deslizamiento establecidas a izquierda y derecha)

Esto significa que la solución original es la forma en que se supone que debe usarse. La propiedad de dirección solo se puede usar para que los gestos se reconozcan correctamente, pero no en el método realizado en un reconocimiento exitoso para comparar la dirección real que activó el reconocimiento.

RupertP
fuente
35
Estoy dispuesto a apostar a que casi todos los que primero usan el reconocedor de gestos de deslizamiento hacen exactamente la misma suposición incorrecta sobre cómo debería funcionar la propiedad de dirección.
memmons 27/10/10
Es una tontería tener que crear 4 reconocedores diferentes para rastrear deslizamientos hacia arriba, abajo, izquierda y derecha, pero ahí estás.
memmons
wow eso apesta, no es un gran problema, pero parece algo que podrían haber agregado
marchinram
2
Su archivo de encabezado dice: @property (nonatomic) UISwipeGestureRecognizerDirection direction; // el valor predeterminado es UISwipeGestureRecognizerDirectionRight. la dirección deseada del deslizamiento. se pueden especificar varias direcciones
nicktmro
1
Convino en que esto parece una implementación extraña por parte de Apple. Debería poder especificar varias direcciones y luego probar una de esas direcciones.
ChrisP
25

Noté que los gestos izquierda / derecha y arriba / abajo funcionan juntos en pares, por lo que solo necesita especificar dos reconocedores de gestos. Y los documentos parecen estar equivocados.

Lars
fuente
Esta es la solución correcta. 2 GR, uno para arriba y abajo / uno para izquierda y derecha. ¡Bingo!
logancautrell
22

Bueno, eso apesta, resolví el problema agregando 2 gestos como mencionó Lars y eso funcionó perfectamente ...

1) Izquierda / Derecha 2) Arriba / Abajo

  

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

Ahora esta es la función 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
fuente
5

Si usa Xcode 4.2, puede agregar Gesture Recognizers @ al guión gráfico y luego vincular los GUI Gesture Recognizers a IBActions.

Puede encontrar los reconocedores de gestos en la biblioteca de objetos del panel de utilidades (la parte inferior del panel derecho).

Entonces es solo una cuestión de Control-arrastrar a la acción apropiada.

Grymm
fuente
5

Si desea que detecte las cuatro direcciones, deberá crear cuatro instancias, como lo hizo en su solución.

He aquí por qué : la misma instancia de UISwipeGestureRecognizer que crea es la instancia que se pasa al selector como remitente. Entonces, si lo configura para reconocer las cuatro direcciones, volverá verdadero parasgr.direction == xxx donde xxx es cualquiera de las cuatro direcciones.

Aquí hay una solución alternativa que implica menos código (supone el uso de 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
fuente
2

Aquí hay un ejemplo de código para el uso de UISwipeGestureRecognizer. Tenga en cuenta los comentarios.

- (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 y swipeLeft son métodos que utiliza para realizar actividades específicas basadas en deslizar hacia la izquierda o hacia la derecha. Por ejemplo:

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

Swift 2.1

Tuve que usar lo siguiente

    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)
    }
Andrei
fuente
1

hmm, extraño, funciona perfecto para mí, hago exactamente lo mismo

creo que deberías intentar mirar

Método UIGestureRecognizerDelegate

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

en los registros debes ver algo como:

debería comenzar a gesticular; target = <(action = actionForUpDownSwipeGestureRecognizer :, target =)>; dirección = arriba, abajo, izquierda, derecha>

iFreeman
fuente
¿Qué no funciona? gestoReconocidorShouldBegin: funciona bien.
Danyal Aytekin
1

use esto, debería ser la operación de bits

   gesture.direction & UISwipeGestureRecognizerDirectionUp || 
   gesture.direction & UISwipeGestureRecognizerDirectionDown
William Wu
fuente
0

Esto me estaba volviendo loco. Finalmente descubrí una forma confiable de tener múltiples swipeGestureRecognizers.

Parece que hay un error en iOS si el nombre de su selector de "acción" es el mismo en múltiples swipeGestureRecognizers. Si solo los nombra de manera diferente, por ejemplo handleLeftSwipeFrom y handleRightSwipeFrom, todo funciona.

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
fuente