UISwipeGestureRecognizerの方向の設定


132

ビューベースのiPhoneプロジェクトに単純なスワイプジェスチャ認識を追加したいのですが。すべての方向(右、下、左、上)のジェスチャーを認識する必要があります。

UISwipeGestureRecognizerのドキュメントに記載されています:

ビットごとのORオペランドを使用して複数のUISwipeGestureRecognizerDirection定数を指定することにより、複数の方向を指定できます。デフォルトの方向はUISwipeGestureRecognizerDirectionRightです。

しかし、私にとってはうまくいきません。4つの方向すべてがOR結合されると、左と右のスワイプのみが認識されます。

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

ビューに4つの認識機能を追加してこれを修正しましたが、ドキュメントで宣伝されているように機能しないのはなぜですか?

- (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
まったく無関係ですが、[super viewDidLoad]; -(void)viewDidLoadの最初のステートメントである必要があります
Mihir Mehta

回答:


115

バグがあるようです。許可された方向を指定したように指定できます。ただし、アクションセレクターメソッドでスワイプをトリガーした実際の方向にアクセスしようとすると、最初に(許可された方向に対して)設定したビットマスクが引き続き取得されます。

つまり、複数の方向が許可されている場合、実際の方向のチェックは常に失敗します。セレクターメソッド(つまり-(void)scrollViewSwiped:(UISwipeGestureRecognizer *)recognizer)で 'direction'の値を出力すると、簡単に確認できます。

バグレポート(#8276386)をアップルに提出しました。

[更新] Appleから、意図したとおりに動作するという回答を得ました。

したがって、たとえばテーブルビューでは、テーブルビューのセルを左または右にスワイプして「削除」をトリガーできます(これにより、スワイプジェスチャーの方向が左および右に設定されます)。

これは、元の回避策が使用されることになっている方法であることを意味します。directionプロパティは、ジェスチャーを正しく認識させるためにのみ使用できますが、認識をトリガーした実際の方向と比較するために成功した認識に対して実行されるメソッドでは使用できません。


35
私が最初にスワイプジェスチャー認識機能を使用するほとんどすべての人が、方向プロパティがどのように機能するかについてまったく同じ誤った仮定をすることに賭けても構わないと思います。
memmons

上、下、左、右のスワイプを追跡するために4つの異なる認識機能を作成する必要があるのはばかげています。
memmons

すごいね、
大した

2
彼らのヘッダーファイルは言う:@property(nonatomic)UISwipeGestureRecognizerDirection direction; //デフォルトはUISwipeGestureRecognizerDirectionRightです。スワイプの目的の方向。複数の方向を指定することができます
nicktmro 2011

1
これはApple側の奇妙な実装のように見えることに同意した。複数の方向を指定して、それらの方向の1つをテストできるはずです。
ChrisP

25

左/右と上/下のジェスチャーはペアで機能するので、2つのジェスチャー認識機能を指定するだけで済みます。そして、ドキュメントは間違っているようです。


これが正しい解決策です。2つのGR、1つは上下、もう1つは左右。ビンゴ!
logancautrell、2011年

22

残念ながら、私はLarsが述べたように2つのジェスチャーを追加することで問題を解決しました。

1)左/右2)上/下

  

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

これが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

Xcode 4.2を使用している場合は、ストーリーボード@ジェスチャー認識機能を追加し、GUIジェスチャー認識機能をIBActionsにリンクできます。

ジェスチャ認識機能は、ユーティリティペインのオブジェクトライブラリ(右ペインの下部)にあります。

次に、Controlキーを押しながら適切なアクションにドラッグします。


5

4つの方向すべてを検出する場合は、回避策で行ったように、4つのインスタンスを作成する必要があります。

理由:作成したUISwipeGestureRecognizerの同じインスタンスが、送信者としてセレクタに渡されるインスタンスです。したがって、4つの方向すべてを認識するように設定した場合、trueが返されますsgr.direction == xxx、xxxが4つの方向のいずれかである。

ここにあります 代替回避策以下のコードを(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

UISwipeGestureRecognizerを使用するためのコードサンプルを以下に示します。コメントに注意してください。

- (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およびswipeLeftは、左または右のスワイプに基づいて特定のアクティビティを実行するために使用するメソッドです。例えば:

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

私は以下を使用しなければなりませんでした

    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

うーん、奇妙です、それは私にとって完璧に機能します、私はまったく同じことをします

見てみるべきだと思います

UIGestureRecognizerDelegateメソッド

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

ログには次のようなものが表示されます:

ジェスチャーを開始する必要があります。target = <(action = actionForUpDownSwipeGestureRecognizer :, target =)>; 方向=上、下、左、右>


何がうまくいかないのですか?GestureRecognizerShouldBegin:正常に動作します。
Danyal Aytekin、2011

1

これを使用してください、それはビット操作でなければなりません

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

0

これは私を夢中にさせていました。私はようやく、複数のswipeGestureRecognizerを使用するための信頼できる方法を見つけました。

「アクション」セレクターの名前が複数のswipeGestureRecognizerで同じである場合、iOSにバグがあるようです。それらに異なる名前を付けるだけの場合、たとえば、handleLeftSwipeFromとhandleRightSwipeFromは、すべて機能します。

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];
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.