2012-07-16 6 views
5

UIWebViewでドキュメントを表示しています。ドキュメント上にホットスポットを配置して、タップしたときにアクションをトリガーしたいのですが、ドキュメントをダブルタップしたときにドキュメントを自動ズームするデフォルトのUIWebViewの動作も維持したいと考えています。私は、ダブルタップにUIWebViewを応答させながら、シングルタップにどのように反応するかを理解することはできません。ダブルタップに応答するオブジェクトを背後に置いて、シングルタップジェスチャにのみ応答する方法はありますか?

まず、ホットスポットをアクション付きのトランスペアレントUIButtonとして設定しましたが、ホットスポットをダブルタップすると、ホットスポットアクションが2回呼び出されました。そこで、ボタンからアクションを削除し、代わりにシングルタップジェスチャーを添付しました。

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapAction:)]; 
singleTap.numberOfTapsRequired = 1; 
singleTap.delegate = self; 
[self.hotspot addGestureRecognizer:singleTap]; 
[singleTap release]; 

これは通常のボタン操作と同じです。しかし、その後、私はダブルタップジェスチャーを作成し、そしてrequireGestureRecognizerToFailとシングルタップジェスチャーにブロックするように設定し:この設定で

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(zoomWebView:)]; 
doubleTap.numberOfTapsRequired = 2; 
doubleTap.delegate = self; 
[self.hotspot addGestureRecognizer:doubleTap]; 
[doubleTap release]; 

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapAction:)]; 
singleTap.numberOfTapsRequired = 1; 
[singleTap requireGestureRecognizerToFail:doubleTap]; 
singleTap.delegate = self; 
[self.hotspot addGestureRecognizer:singleTap]; 
[singleTap release]; 

- (void)zoomWebView:(UITapGestureRecognizer *)gesture { 
    NSLog(@"double tap"); 
} 

を、ホットスポットのシングルタップはsingleTapActionとのダブルタップを呼び出しますホットスポットはzoomWebView(カスタムメソッド)を呼び出します。これは良いことです。なぜなら、singleTapActionはもう2回呼び出されなくなりましたが、UIWebViewがダブルタップに応答しなくなったためです。

ダブルタップジェスチャーからUIWebViewへのダブルタップイベントの転送を試みました.UITapGestureRecognizerをサブクラス化し、touchesBeganおよびtouchesEndedメソッドをオーバーライドし、引数をUIWebViewの対応するメソッドに送信しました。私がそれをしたとき、私のサブクラスがイベントを受け取っていたのを見ることができましたが、UIWebViewは転送されたイベントに応答しませんでした。 は、UIKitフレームワークオブジェクトではなく、UIViewのカスタムサブクラスにのみイベントを転送できると述べているため、これが予想されます。

ダブルタップのイベントを迂回しないダブルタップにシングルタップジェスチャが応答しないようにする方法はありますか?これは基本的な要件のようですが、私はそれを行うための簡単な方法を見ることはできません。私はUIGestureRecognizerのtouch delivery propertiesを読んで実験しましたが、値の組み合わせはシングルタップジェスチャーがダブルタップジェスチャーを消費するのを止めませんでした。

ところで、ビュー階層内のホットスポットとUIWebViewの関係は、「いとこ」のものです。これらは2つの兄弟ビューのサブビューです。ジェスチャ認識機能をホットスポット表示、ウェブ表示または「祖父母」表示に追加すると、同じ結果が得られます。

+0

わからない、しかし、あなたはにシングルタップジェスチャーを追加することはできません。 UIWebView? –

+0

@DeanPucsek私はしばらくそれをやっていたし、PDF文書を表示するときに機能しました。しかし、UIWebViewに表示されているコンテンツがHTMLまたはJPGの場合、UIWebViewは独自のアクションのためにシングルタップをキャプチャし、UIGestureRecognizerはイベントを受信しません。これをホットスポットビューで処理する方が便利ですが、すべてのUIWebViewコンテンツタイプで動作させることができれば、このアプローチに戻ることができます。 – arlomedia

答えて

15

さて、私は2つの部分で解決策を見つけた:

1)私はのUIWebViewの親ビューに私のジェスチャーを追加する必要がありました。比類なきイベントは、私が想像していたように、レイヤーからレイヤーへのビューでオーバーラップするオブジェクトを通って移動しません。代わりに、彼らは子供から親にビューの階層を移動します。UIWebViewの兄弟または「いとこ」ビューにダブルタップジェスチャを追加していた限り、Webビューに進むことは決してありませんでした。つまり、Interface Builderでレイアウトされたボタンやビューを使用して、複数のホットスポット領域を特定することはできません。代わりに、すべてのシングルタップ・イベントを1つの方法にリダイレクトしてから、タッチ位置を調べて、トリガーするアクションを判断する必要があります。

2)gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:メソッドをビューコントローラ(私のジェスチャの代理人)に追加してYESを返す必要がありました。これにより、UIWebViewにHTML、テキスト、またはイメージコンテンツを表示していても、これらのコンテンツタイプに対して独自のジェスチャを実装する場合でも、シングルタップジェスチャが応答するようになります。私はthis answerからこの部分を学びました。

は、これらの変更により、私がするイベントの階層構造を理解:

  • シングルタップWeb表示:Web表示の親ビューで私のシングルタップジェスチャーが応答します。同時ジェスチャが有効になっているため、Webビューのシングルタップジェスチャも応答します。

  • ダブルタップWebビュー:Webビューの親ビューのダブルタップジェスチャは応答しますが(何もしません)。私のシングルタップジェスチャーは、ダブルタップが失敗した場合にのみ応答するように設定されているため応答しません。 Webビューのダブルタップ・イベントは、ビュー階層の一部であるため応答します(Webビューのダブルタップ機能はジェスチャーを使用していないように見えます。そうしないと、元のセットアップでの自分のジェスチャーより優先されるからです) )の方法のうちその説明を

、ここでいくつかの作業コードです:この(したがって、それはコメントである)について

- (void)viewDidLoad { 
    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapWebView:)]; 
    doubleTap.numberOfTapsRequired = 2; 
    doubleTap.delegate = self; 
    [self.webViewParent addGestureRecognizer:doubleTap]; 
    [doubleTap release]; 

    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapWebView:)]; 
    singleTap.numberOfTapsRequired = 1; 
    [singleTap requireGestureRecognizerToFail:doubleTap]; 
    singleTap.delegate = self; 
    [self.webViewParent addGestureRecognizer:singleTap]; 
    [singleTap release]; 
} 

- (void)doubleTapWebView:(UITapGestureRecognizer *)gesture { 
    NSLog(@"double-tap"); 
    // nothing to do here 
} 

- (void)singleTapWebView:(UITapGestureRecognizer *)gesture { 
    NSLog(@"single-tap"); 
    CGPoint touchLocation = [gesture locationInView:self.webViewParent]; 
    float x = touchLocation.x; 
    float y = touchLocation.y; 
    CGRect frame = self.webViewParent.frame; 
    if (y < frame.size.height * .33) { 
     NSLog(@"top"); 
    } else if (y > frame.size.height * .67) { 
     NSLog(@"bottom"); 
    } else if (x < frame.size.width * .33) { 
     NSLog(@"left"); 
    } else if (x > frame.size.width * .67) { 
     NSLog(@"right"); 
    } else { 
     NSLog(@"center"); 
    } 
} 

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 
    return YES; 
} 
+0

ありがとうございます。それは私の状況を最も緊密にターゲットにしており、十数個の記事を読んだ後に解決策を提示しています。大きな仕事の平和。 – vedrano

+0

もちろん+1。優れた説明と優れたコード、Swift 2.1で動作確認済み –

-2

イベント処理が開始されて以来、常にマウスクリックに問題がありました。

ダブルクリックが起きることをソフトウェアが判断するのは、シングルクリックのインスタンスでは不可能です。

したがって、シングルクリックとダブルクリックを処理したい場合は、独自のダブルクリック処理を行う必要があります。

時間シングルクリックのインスタンス、および独自のダブルクリックイベントを発生させます。

あなたのコンテキストでタップに転送することができますうまくいけば。

+0

実際には、iOSでは、UIGestureRecognizerには、シングルタップイベントを発生させる前にダブルタップの期間待機する機能が組み込まれています。そのため、2つの異なるジェスチャ認識機能を使用して2つのイベントを正しくキャプチャすることができます。ダブルタップジェスチャを無視してUIWebViewに到達する方法や、Webビューのビルトインズーム動作を保持するためにそこにリダイレクトする方法はわかりません。 – arlomedia

+0

@arlomedia [iOSイベント転送](https://www.google.com/search?btnG=1&pws=0&q=iOS+event+forwarding) –

+0

私はこれらの検索結果を見ましたが、私に役立つものは見当たりません状況。 UIKitオブジェクトにイベントを転送しようとするべきではないとの提案があります。私の質問の「おそらく簡単な方法があるかもしれません。 – arlomedia

関連する問題