Ustawianie kierunku dla UISwipeGestureRecognizer

132

Chcę dodać proste rozpoznawanie gestów przesunięcia do mojego projektu iPhone'a opartego na widoku. Należy rozpoznawać gesty we wszystkich kierunkach (w prawo, w dół, w lewo, w górę).

Jest to określone w dokumentacji dla UISwipeGestureRecognizer:

Możesz określić wiele kierunków, określając wiele stałych UISwipeGestureRecognizerDirection przy użyciu operandów bitowych-OR. Domyślnym kierunkiem jest UISwipeGestureRecognizerDirectionRight.

Jednak dla mnie to nie działa. Gdy wszystkie cztery kierunki zostaną wykonane LUB rozpoznawane są tylko przesunięcia w lewo i w prawo.

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

Naprawiłem to, dodając cztery narzędzia rozpoznające do widoku, ale jestem ciekawy, dlaczego nie działa tak, jak reklamowano w dokumentach?

- (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
źródło
3
jest całkowicie niepowiązany, ale [super viewDidLoad]; powinny być pierwsze pismo w - (void) viewDidLoad
Mihir Mehta

Odpowiedzi:

115

Wygląda na to, że jest błąd. Możesz określić dozwolone kierunki, tak jak zrobiłeś. Ale kiedy próbujesz uzyskać dostęp do rzeczywistego kierunku, który wywołał przesunięcie w metodzie selektora akcji, nadal uzyskujesz pierwotnie ustawioną maskę bitową (dla dozwolonych kierunków).

Oznacza to, że sprawdzenie rzeczywistego kierunku zawsze kończy się niepowodzeniem, gdy dozwolony jest więcej niż 1 kierunek. Możesz to zobaczyć na własne oczy, gdy podajesz wartość 'direction' w metodzie selektora (tj -(void)scrollViewSwiped:(UISwipeGestureRecognizer *)recognizer.).

Zgłosił błąd (nr 8276386) do Apple.

[Aktualizacja] Otrzymałem odpowiedź od Apple, mówiącą, że zachowanie działa zgodnie z zamierzeniami.

Na przykład w widoku tabeli możesz przesunąć palcem w lewo lub w prawo w komórce widoku tabeli, aby wywołać `` usuwanie '' (to miałoby kierunki gestu przesunięcia ustawione na lewo i prawo)

Oznacza to, że pierwotne obejście jest sposobem, w jaki powinno być używane. Właściwość direction może być używana tylko do prawidłowego rozpoznawania gestów, ale nie w metodzie wykonanej po pomyślnym rozpoznaniu, aby porównać rzeczywisty kierunek, który wyzwolił rozpoznanie.

RupertP
źródło
35
Jestem skłonny założyć się, że prawie każdy, kto pierwszy używa rozpoznawania gestów machnięcia, przyjmuje dokładnie to samo niepoprawne założenie dotyczące działania właściwości kierunku.
memmons
Głupio jest tworzyć 4 różne urządzenia rozpoznające, aby śledzić przesunięcia w górę, w dół, w lewo iw prawo, ale tak jest.
memmons
wow, to trochę do bani, nie jest to wielka sprawa, ale wygląda na to, że mogliby coś dodać
marchinram
2
Ich plik nagłówkowy mówi: @property (nonatomic) UISwipeGestureRecognizerDirection direction; // wartość domyślna to UISwipeGestureRecognizerDirectionRight. żądany kierunek machnięcia. można określić wiele kierunków
nicktmro
1
Zgodziłem się, że wydaje się to dziwną implementacją ze strony Apple. Powinieneś móc określić wiele kierunków, a następnie przetestować jeden z tych kierunków.
ChrisP,
25

Zauważyłem, że gesty w lewo / w prawo i w górę / w dół działają razem w parach, więc wystarczy określić dwa urządzenia do rozpoznawania gestów. A doktorzy wydają się być w błędzie.

Lars
źródło
To jest poprawne rozwiązanie. 2 GR, jeden do góry i do dołu / jeden do lewej i prawej. Bingo!
logancautrell
22

Cóż, to jest do bani, rozwiązałem problem, dodając 2 gesty, takie jak wspomniał Lars, i działało idealnie ...

1) Lewo / Prawo 2) Góra / Dół

  

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
źródło
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];

To jest funkcja 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
źródło
5

Jeśli używasz Xcode 4.2, możesz dodać Gesture Recognizers @ the storyboard, a następnie połączyć GUI Gesture Recognizers z IBActions.

Rozpoznawanie gestów można znaleźć w bibliotece obiektów w okienku narzędziowym (na dole prawego panelu).

Wtedy wystarczy przeciągnąć klawisz Control do odpowiedniego działania.

Grymm
źródło
5

Jeśli chcesz, aby wykrywał wszystkie cztery kierunki, musisz utworzyć cztery instancje, tak jak w przypadku obejścia.

Oto dlaczego : To samo wystąpienie UISwipeGestureRecognizer, które tworzysz, jest instancją, która jest przekazywana do selektora jako nadawca. Więc jeśli ustawisz rozpoznawanie wszystkich czterech kierunków, zwróci prawdę, gdy sgr.direction == xxxxxx jest jednym z czterech kierunków.

Oto alternatywne obejście, które obejmuje mniej kodu (zakłada użycie 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
źródło
3

Swift 2.1

Musiałem użyć następującego

    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
źródło
2

Oto przykład kodu do użycia UISwipeGestureRecognizer. Uwaga komentarze.

- (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 i swipeLeft to metody używane do wykonywania określonych czynności na podstawie przesuwania w lewo lub w prawo. Na przykład:

- (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
źródło
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
źródło
1

hmm, dziwne, u mnie działa idealnie, robię dokładnie to samo

myślę, że powinieneś spróbować spojrzeć

UIGestureRecognizerDelegate, metoda

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

w logach musisz zobaczyć coś takiego:

powinien zacząć gest; target = <(action = actionForUpDownSwipeGestureRecognizer :, target =)>; kierunek = góra, dół, lewo, prawo>

iFreeman
źródło
Co nie działa? gestRecognizerShouldBegin: działa dobrze.
Danyal Aytekin,
1

użyj tego, powinna to być operacja bitowa

   gesture.direction & UISwipeGestureRecognizerDirectionUp || 
   gesture.direction & UISwipeGestureRecognizerDirectionDown
William Wu
źródło
0

To doprowadzało mnie do szału. W końcu znalazłem niezawodny sposób na posiadanie wielu swipeGestureRecognizers.

Wygląda na to, że w systemie iOS występuje błąd, jeśli nazwa selektora „akcji” jest taka sama dla wielu urządzeń swipeGestureRecognizers. Jeśli nadasz im inną nazwę, np. HandleLeftSwipeFrom i handleRightSwipeFrom, wszystko działa.

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
źródło