25

ユーザーが画面上の線をトレースできるアプリがあります。私は UIPanGestureRecognizer 内のポイントを記録することでそうしています:

-(void)handlePanFrom:(UIPanGestureRecognizer *)recognizer
{
    CGPoint pixelPos = [recognizer locationInView:rootViewController.glView];
    NSLog(@"recorded point %f,%f",pixelPos.x,pixelPos.y);
}

それはうまくいきます。ただし、ユーザーがパンを開始する前にタップした最初のポイントに非常に興味があります。しかし、上記のコードでは、ジェスチャがパン (タップではなく) として認識されたに発生したポイントしか得られません。

ドキュメントから、UIPanGestureRecognizer API 内で最初にタップされた場所を特定する簡単な方法がないように見えます。UIPanGestureRecognizer.h 内ですが、次の宣言を見つけました。

CGPoint _firstScreenLocation;

...これは非公開のようですので、運が悪いです。UIGestureRecognizer システムの外に完全に出て、最初にタップされたポイントをキャプチャし、ユーザーが実際に UIPanGesture を開始したことがわかったら後で参照することを検討しています。でも、その道を進む前に、ここで聞いてみようと思いました。

4

8 に答える 8

21

translationInView:途中でリセットしない限り、を使用して開始位置を計算できるはずです。翻訳とタッチの現在位置を取得し、それを使用してタッチの開始点を見つけます。

于 2011-08-05T02:35:04.157 に答える
1

このメソッドに入れられた同じ UIView で。

//-----------------------------------------------------------------------
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGPoint point = [[[event allTouches] anyObject] locationInView:self];
NSLog(@"point.x ,point.y  : %f, %f",point.x ,point.y);
}

ここのUIGestureRecognizer Class Referenceで探してください: https://developer.apple.com/library/ios/documentation/uikit/reference/UIGestureRecognizer_Class/Reference/Reference.html

于 2014-04-17T01:32:37.353 に答える
0

また、UIPanGestureRecognizer の shouldBegin メソッドで値を読み取ろうとすると、ユーザーが少し移動した後 (つまり、ジェスチャーがパンを認識し始めたとき) にのみその位置が表示されることに気付きました。このパン ジェスチャが実際に開始された場所を知ることは非常に便利です。これにより、認識すべきかどうかを判断できます。

UIGestureRecognizer ビューをサブクラス化したくない場合は、次の 2 つのオプションがあります。

  1. UILongPressGestureRecognizer、遅延を 0 に設定
  2. UIPanGestureRecognizer、および shouldReceiveTouch での開始点のキャプチャ

他のジェスチャ (タップ、ダブルタップなど) がある場合は、オプション 2 が必要になる可能性があります。遅延が 0 のジェスチャ レコグナイザを長押しすると、他のジェスチャが正しく認識されなくなるためです。

他のジェスチャーを気にせず、パンのみを適切に機能させたい場合は、UILongPressGestureRecognizer を遅延 0 で使用できます。開始を手動で追跡する必要がないため、維持が容易になります。点。


解決策 1: UILongPressGestureRecognizer

良い点: シンプル

悪い点: 他のジェスチャー ハンドラーとうまくやっていく

ジェスチャを作成するときは、minimumPressDurationをに設定して0ください。これにより、すべてのデリゲート メソッド (begin など) が最初のタッチを適切に受け取ることが保証されます。

UILongPressGestureRecognizer は継続的なジェスチャレコグナイザーであるため (個別のジェスチャ レコグナイザーではなく)、UIPanGestureRecognizer (継続的なジェスチャ レコグナイザーでもある) の場合と同様に、 UIGestureRecognizer.State.changedプロパティを処理することで動きを処理できます。基本的に、2 つのジェスチャを組み合わせています。

let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(gestureHandler(_:))
gestureRecognizer.minimumPressDuration = 0

解決策 2: UIPanGestureRecognizer

用途: 他のジェスチャ レコグナイザーとうまく組み合わせる

悪い点: 開始状態を保存するのにもう少し手間がかかる

手順:

  1. まず、デリゲートとして登録し、shouldReceiveTouch イベントをリッスンする必要があります。

  2. それが発生したら、タッチポイントを何らかの変数に保存します (ジェスチャ ポイントではありません!)。

  3. 実際にジェスチャを開始するかどうかを決定するときが来たら、この変数を読み取ります。

var gestureStartPoint: CGPoint? = nil

// ...

let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(gestureHandler(_:))
gestureRecognizer.delegate = self

// ...

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    gestureStartPoint = touch.location(in: self)
    return true
}

警告:前者が開始位置を正確に取得する唯一の方法であるため、必ず読んtouch.location(in: self)でください。gestureRecognizer.location(in: self)

gestureStartPoint次のように、好きな場所で使用できるようになりました。

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    return isValidStartPoint(gestureStartPoint!)
}
于 2020-03-08T22:52:29.963 に答える
-2

UIGestureRecognizerStateBegan メソッドを使用できます。UIGestureRecognizer クラスに関する Apple ドキュメントへのリンクは次のとおりです。

http://developer.apple.com/library/ios/ipad/#documentation/uikit/reference/UIGestureRecognizer_Class/Reference/Reference.html%23//apple_ref/occ/cl/UIGestureRecognizer

于 2011-08-05T02:34:41.427 に答える
-3

うわー、数年遅れて..私はこの問題に遭遇しましたが、静的変数で解決しました:

- (IBAction)handleGesture:(UIPanGestureRecognizer *)recog {

    CGPoint loc = [recognizer locationInView:self.container];
    static CGFloat origin = 0.0f;

    switch (recognizer.state) {
        case UIGestureRecognizerStateBegan:
            origin = loc.x;
            break;
        case UIGestureRecognizerStateChanged:
        case UIGestureRecognizerStatePossible:
            // origin is still set here to the original touch point!
            break;
        case UIGestureRecognizerStateEnded:
            break;
        case UIGestureRecognizerStateFailed:
        case UIGestureRecognizerStateCancelled:
            break;
    }

}

この変数は、認識エンジンの状態が UIGestureRecognizerBegan の場合にのみ設定されます。変数は静的であるため、値は後のメソッド呼び出しまで保持されます。

私の場合、必要なのは x 座標だけでしたが、必要に応じて CGPoint に変更できます。

于 2016-12-07T04:35:46.197 に答える