web-dev-qa-db-ja.com

4つの方向すべてのスワイプを認識する方法は?

全方向のスワイプを認識する必要があります(上/下/左/右)。同時にではありませんが、私はそれらを認識する必要があります。

私は試した:

  UISwipeGestureRecognizer *Swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(SwipeRecognizer:)];
  Swipe.direction = (UISwipeGestureRecognizerDirectionLeft | 
                     UISwipeGestureRecognizerDirectionRight |
                     UISwipeGestureRecognizerDirectionDown | 
                     UISwipeGestureRecognizerDirectionUp);
  [self.view addGestureRecognizer:Swipe];
  [Swipe release];

SwipeRecognizerには何も表示されませんでした

SwipeRecognizerのコードは次のとおりです。

- (void) SwipeRecognizer:(UISwipeGestureRecognizer *)sender {
  if ( sender.direction == UISwipeGestureRecognizerDirectionLeft )
    NSLog(@" *** SWIPE LEFT ***");
  if ( sender.direction == UISwipeGestureRecognizerDirectionRight )
    NSLog(@" *** SWIPE RIGHT ***");
  if ( sender.direction == UISwipeGestureRecognizerDirectionDown )
    NSLog(@" *** SWIPE DOWN ***");
  if ( sender.direction == UISwipeGestureRecognizerDirectionUp )
    NSLog(@" *** SWIPE UP ***");
}

これどうやってするの? Swipeオブジェクトにすべての異なる方向を割り当てるにはどうすればよいですか?

26
elp

このように方向を設定します

  UISwipeGestureRecognizer *Swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(SwipeRecognizer:)];
  Swipe.direction = (UISwipeGestureRecognizerDirectionLeft | 
                     UISwipeGestureRecognizerDirectionRight |
                     UISwipeGestureRecognizerDirectionDown | 
                     UISwipeGestureRecognizerDirectionUp);

それがコールバックを取得するときの方向です。そのため、すべてのテストが失敗するのは通常のことです。もしあったなら

- (void) SwipeRecognizer:(UISwipeGestureRecognizer *)sender {
  if ( sender.direction | UISwipeGestureRecognizerDirectionLeft )
    NSLog(@" *** SWIPE LEFT ***");
  if ( sender.direction | UISwipeGestureRecognizerDirectionRight )
    NSLog(@" *** SWIPE RIGHT ***");
  if ( sender.direction | UISwipeGestureRecognizerDirectionDown )
    NSLog(@" *** SWIPE DOWN ***");
  if ( sender.direction | UISwipeGestureRecognizerDirectionUp )
    NSLog(@" *** SWIPE UP ***");
}

テストは成功します(ただし、テストはすべて成功するため、テストから情報を取得することはありません)。異なる方向のスワイプを区別したい場合は、別個のジェスチャー認識機能が必要になります。


編集

コメントで指摘されているように、 この答え を参照してください。どうやらこれは動作しません。人生を楽にするために、一方向のみのスワイプを作成する必要があります。

21
jbat100

私は以前にこの正確な問題に実際に遭遇しました。私がやったことは、UIViewサブクラスを作成し、touchesMoved:をオーバーライドして、方向を計算するためにいくつかの計算を行うことでした。

一般的な考え方は次のとおりです。

#import "OmnidirectionalControl.h"

typedef NS_ENUM(NSInteger, direction) {
    Down = 0, DownRight = 1,
    Right = 2, UpRight = 3,
    Up = 4, UpLeft = 5,
    Left = 6, DownLeft = 7
};

@interface OmnidirectionalControl ()

@property (nonatomic) CGPoint startTouch;
@property (nonatomic) CGPoint endTouch;

@end

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    self.startTouch = [[touches allObjects][0] locationInView:self];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    self.lastTouch = [[[touches allObjects] lastObject] locationInView:self];
    NSLog(@"Direction: %d", [self calculateDirectionFromTouches]);
}

-(direction)calculateDirectionFromTouches {
    NSInteger xDisplacement = self.lastTouch.x-self.startTouch.x;
    NSInteger yDisplacement = self.lastTouch.y-self.startTouch.y;

    float angle = atan2(xDisplacement, yDisplacement);
    int octant = (int)(round(8 * angle / (2 * M_PI) + 8)) % 8;

    return (direction) octant;
}

touchesMoved:では簡単にするために、方向をログに記録するだけですが、その情報でやりたいことを実行できます(たとえば、デリゲートに渡したり、通知を投稿したりできます)。 touchesMovedでは、スワイプが終了したかどうかを認識するための方法も必要ですが、それは質問とはあまり関係がないので、それはあなたにお任せします。 calculateDirectionFromTouchesの数学について説明します ここ

4
pasawaya

残念ながら、認識機能をリッスンするためにdirectionプロパティを使用することはできません。認識機能によって検出された方向のみを提供します。その目的で2つの異なるUISwipeGestureRecognizersを使用しました。ここで私の回答を参照してください: https://stackoverflow.com/a/16810160/936957

4

ようやく最も簡単な答えが見つかりました。同意する場合は、これを答えとしてマークしてください。

1方向のスワイプ+パンしかない場合は、次のように言うだけです。[myPanRecogznier requireGestureRecognizerToFail:mySwipeRecognizer];

しかし、2つ以上のスワイプがある場合、そのメソッドに配列を渡すことはできません。そのために、実装する必要があるUIGestureRecognizerDelegateがあります。

たとえば、2つのスワイプ(左と右)を認識し、ユーザーがパンできるようにしたい場合は、ジェスチャ認識機能をプロパティまたはインスタンス変数として定義し、VCパンジェスチャー認識機能のデリゲートとして:

_swipeLeft = [[UISwipeGestureRecognizer alloc] ...]; // use proper init here
_swipeRight = [[UISwipeGestureRecognizer alloc] ...]; // user proper init here
_swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
_swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
_pan = [[UIPanGestureRecognizer alloc] ...]; // use proper init here

_pan.delegate = self;

// then add recognizers to your view

次に、-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer delegate methodを次のように実装します:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if (gestureRecognizer == _pan && (otherGestureRecognizer == _swipeLeft || otherGestureRecognizer == _swipeRight)) {
        return YES;
    }

    return NO;
}

これにより、パンジェスチャーレコグナイザーは、左と右の両方のスワイプが認識されない場合にのみ機能するようになります-完璧です!

うまくいけば、将来的にはAppleによって、配列をrequireGestureRecognizerToFail:メソッドに渡すことができます。

2

SwipeGestureで対角線を1つだけ追加できます...

    UISwipeGestureRecognizer *swipeV = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(action)];
    UISwipeGestureRecognizer *swipeH = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(action)];
    swipeH.direction = ( UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight  );
    swipeV.direction = ( UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown );
    [self addGestureRecognizer:swipeH];
    [self addGestureRecognizer:swipeV];
     self.userInteractionEnabled = YES;
1
Damien Romito
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");
}
0
bhavik

これは最善の解決策ではないかもしれませんが、検出したいスワイプの方向ごとにいつでも異なるUISwipeGestureRecognizerを指定できます。

ViewDidLoadメソッドでは、必要なUISwipeGestureRecognizerを定義するだけです。

- (void)viewDidLoad{
    UISwipeGestureRecognizer *recognizerUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeUp:)];
    recognizerUp.direction = UISwipeGestureRecognizerDirectionUp;
    [[self view] addGestureRecognizer:recognizerUp];

    UISwipeGestureRecognizer *recognizerDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeDown:)];
    recognizerDown.direction =  UISwipeGestureRecognizerDirectionDown;
    [[self view] addGestureRecognizer:recognizerDown];
}

次に、スワイプを処理するそれぞれのメソッドを実装します。

- (void)handleSwipeUp:(UISwipeGestureRecognizer *)sender{
    if (sender.state == UIGestureRecognizerStateEnded){
        NSLog(@"SWIPE UP");
    }
}


- (void)handleSwipeDown:(UISwipeGestureRecognizer *)sender{
    if (sender.state == UIGestureRecognizerStateEnded){
        NSLog(@"SWIPE DOWN");
    }
}

UIPanGestureRecogizerを使用して、気になるスワイプの方向を検出します。詳細については、UIPanGestureRecognizerのドキュメントを参照してください。 -rrh

// add pan recognizer to the view when initialized
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panRecognized:)];
[panRecognizer setDelegate:self];
[self addGestureRecognizer:panRecognizer]; // add to the view you want to detect swipe on


-(void)panRecognized:(UIPanGestureRecognizer *)sender
{
    if (sender.state == UIGestureRecognizerStateBegan) {
        // you might want to do something at the start of the pan
    }

    CGPoint distance = [sender translationInView:self]; // get distance of pan/swipe in the view in which the gesture recognizer was added
    CGPoint velocity = [sender velocityInView:self]; // get velocity of pan/swipe in the view in which the gesture recognizer was added
    float usersSwipeSpeed = abs(velocity.x); // use this if you need to move an object at a speed that matches the users swipe speed
    NSLog(@"swipe speed:%f", usersSwipeSpeed);
    if (sender.state == UIGestureRecognizerStateEnded) {
        [sender cancelsTouchesInView]; // you may or may not need this - check documentation if unsure
        if (distance.x > 0) { // right
            NSLog(@"user swiped right");
        } else if (distance.x < 0) { //left
            NSLog(@"user swiped left");
        }
        if (distance.y > 0) { // down
            NSLog(@"user swiped down");
        } else if (distance.y < 0) { //up
            NSLog(@"user swiped up");
        }
        // Note: if you don't want both axis directions to be triggered (i.e. up and right) you can add a tolerence instead of checking the distance against 0 you could check for greater and less than 50 or 100, etc.
    }
}

CHANHE with STATEEND CODE WITH WWITH

//上、下、左、右から1回だけスワイプしたい場合

if (sender.state == UIGestureRecognizerStateEnded) {
        [sender cancelsTouchesInView]; // you may or may not need this - check documentation if unsure
        if (distance.x > 0 && abs(distance.x)>abs(distance.y)) { // right
            NSLog(@"user swiped right");
        } else if (distance.x < 0 && abs(distance.x)>abs(distance.y)) { //left
            NSLog(@"user swiped left");
        }
        if (distance.y > 0 && abs(distance.y)>abs(distance.x)) { // down
            NSLog(@"user swiped down");
        } else if (distance.y < 0 && abs(distance.y)>abs(distance.x)) { //up
            NSLog(@"user swiped up");
        }

    } 
0
Richie Hyatt