6

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がダブルタップに応答しなくなったため悪いことです。

UITapGestureRecognizerをサブクラス化し、touchesBeganメソッドとtouchesEndedメソッドをオーバーライドし、それらの引数をUIWebViewの対応するメソッドに送信することにより、doubleTapジェスチャからUIWebViewにダブルタップイベントを転送しようとしました。これを行うと、サブクラスがイベントを受信して​​いることがわかりましたが、UIWebViewは転送されたイベントに応答しませんでした。iOSのイベント処理ガイドでは、イベントはUIKitフレームワークオブジェクトではなく、UIViewのカスタムサブクラスにのみ転送できると記載されているため、これは予想されることです。

シングルタップジェスチャがダブルタップイベントを迂回させないダブルタップに応答しないようにする方法はありますか?これは基本的な要件のように思えますが、それを行うための簡単な方法がわかりません。UIGestureRecognizerのタッチ配信プロパティについて読んで実験しましたが、値の組み合わせによって、シングルタップジェスチャがダブルタップジェスチャを消費するのを防ぐことはできませんでした。

ちなみに、私のビュー階層におけるホットスポットとUIWebViewの関係は、「いとこ」の関係です。これらは、2つの兄弟ビューのサブビューです。ホットスポットビュー、Webビュー、またはそれらの「祖父母」ビューにジェスチャレコグナイザーを追加すると、同じ結果が得られます。

4

2 に答える 2

15

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

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

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

これらの変更により、イベントの階層は次のようになると理解しています。

  • シングルタップ 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;
}
于 2012-07-17T18:42:38.450 に答える
-2

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

シングル クリックの瞬間に、ダブル クリックが発生しようとしていることをソフトウェアが判断することは不可能です。

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

シングル クリックのインスタンスの時間を計り、独自のダブル クリック イベントを生成します。

うまくいけば、それがあなたの文脈でタッピングに移ることができます.

于 2012-07-17T00:05:51.600 に答える