web-dev-qa-db-ja.com

UISwipeGestureRecognizerの方向を設定する

ビューベースの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.");
}
131
sandisn

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

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

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

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

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

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

114
RupertP

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

25
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];
22
yunas
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
      }
 }
13
KarenAnne

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

理由はこちら:UISwipeGestureRecognizerの同じインスタンスが、送信者としてセレクターに渡されるインスタンスです。したがって、4つの方向すべてを認識するように設定すると、sgr.direction == xxxに対してtrueが返されます。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];
}
5
tybro0103

Xcode 4.2を使用している場合は、Gesture Recognizersをストーリーボードに追加してから、GUI Gesture RecognizersをIBActionsにリンクできます。

ジェスチャレコグナイザーは、ユーティリティペイン(右ペインの下部)のオブジェクトライブラリにあります。

次に、適切なアクションにコントロールをドラッグするだけの問題。

5
Grymm

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
Greg
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
bhavik

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)
    }
2
Andrei

これを使用して、ビット操作にする必要があります

   gesture.direction & UISwipeGestureRecognizerDirectionUp || 
   gesture.direction & UISwipeGestureRecognizerDirectionDown
1
William Wu

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

見てみるべきだと思う

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 =)>;方向=上、下、左、右>

1
iFreeman

これは私を夢中にさせました。最後に、複数のswipeGestureRecognizerを使用する信頼できる方法を見つけました。

「アクション」セレクターの名前が複数のswipeGestureRecognizersで同じ場合、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];
0
Alex