41

UIScrollView のサブビューである UIWebview で動作する UIGestureRecognizer を取得しようとしています。これは奇妙に聞こえますが、numberOfTouchesRequiredセットを 2 にするとセレクターが起動しますが、numberOfTouchesRequired1 に設定するとセレクターは起動しません。

これが私のコードです:

UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(select1:)];
    tap1.numberOfTouchesRequired = 2;
    tap1.numberOfTapsRequired = 1;
    tap1.delegate = self;
    [self.ans1WebView addGestureRecognizer:tap1];
    [tap1 release];

- (void) select1:(UILongPressGestureRecognizer *)sender {
    //Do Stuff
}

UIGestureRecognizer の Apple サンプルを使用し、ペン先に webview を挿入することで、これを確認しました。彼らのタップコードはどこでも機能しますが、webview の領域内です。

4

7 に答える 7

68

私が見たところ、UIWebViewは他の人とうまく機能しません。ジェスチャレコグナイザーの場合、以下からYESを返すことを試みることができます。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

3.0との下位互換性が必要だったため、UIWebView内でJavascriptを使用してすべてのジェスチャ処理を行うことになりました。良い解決策ではありませんが、それは私のニーズには合いました。要素を長押ししたり、タップ、スワイプ、ピンチ、回転したりすることができました。もちろん、私はローカルコンテンツのみを使用していました。

編集:

UIWebViewのデリゲートにメッセージを送信する例については、 PhoneGapを参照してください。簡単に言うdocument.location = "myscheme:mycommand?myarguments"と、このデリゲートコールバックからコマンドと引数を使用して解析します。

-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
  if ( [[[inRequest URL] absoluteString] hasPrefix:@"myscheme:"] ) {
    //.. parse arguments
    return NO;
  }
}

PhoneGapコードで、メッセージを送信するためのキューとタイマーが設定されていることがわかります。使用法によっては、同じことをする必要があるかもしれません。このトピックに関するSOに関する他の質問があります。

これがイベント処理のドキュメントです。私の場合、documentからにイベントリスナーを追加しました<body onload="myloader();">

function myloader() {
    document.addEventListener( 'touchcancel' , touch_cancel , false );
    document.addEventListener( 'touchstart' , touch_start , false );
    document.addEventListener( 'touchmove' , touch_move , false );
    document.addEventListener( 'touchend' , touch_end , false );
};

実際のイベント処理は、ニーズによって大きく異なります。各イベントハンドラーは、各アイテムがTouchであるtouchesプロパティを持つTouchEventを受け取ります。タッチスタートハンドラーで開始時間と場所を記録できます。タッチが遠くに移動したり、間違った時間が経過したりした場合、それは長いタッチではありません。

WebKitは、選択とコピーを開始するために長いタッチを処理しようとする場合があります。event.preventDefault();イベントハンドラーでは、デフォルトの動作を停止するために使用できます。また、-webkit-user-select:nonecssプロパティがいくつかの点で便利であることがわかりました。

var touch = {};
function touch_start( event /*TouchEvent*/ {
  event.preventDefault();
  touch = {};
  touch.startX = event.touches.item(0).pageX;
  touch.startY = event.touches.item(0).pageY;
  touch.startT = ( new Date() ).getTime();
}

これは私がjavascriptを使用した2番目のプロジェクトです。他の場所でより良い例を見つけることができます。

ご覧のとおり、これは問題に対する迅速な答えではありません。得られた結果にはかなり満足しています。私が使用していたhtmlには、1つまたは2つのリンク以外のインタラクティブな要素はありませんでした。

于 2010-05-26T03:15:58.070 に答える
45

UIWebView には独自のプライベート ビューがあり、これにはジェスチャ レコグナイザーもアタッチされています。したがって、優先順位規則により、UIWebView に追加されたジェスチャ レコグナイザーが適切に機能しなくなります。

1 つのオプションは、UIGestureRecognizerDelegate プロトコルを実装し、メソッド ジェスチャRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer を実装することです。他のタップ ジェスチャについては、このメソッドから YES を返します。このようにして、タップ ハンドラーが呼び出され、Web ビューも呼び出されます。

Apple dev フォーラムでこれを参照してください。

于 2010-10-22T01:29:54.730 に答える
13

これはややハックっぽいソリューションですが、機能します。UIWebView には、通常はプライベート API を使用しないとアクセスできない多くの内部ジェスチャ レコグナイザーがあります。ただし、実装すると、それらはすべて無料で入手できますgestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:。その時点で、すべての内部 UITapGestureRecognizer に、独自の UITapGestureRecognizer が失敗した場合にのみ起動するように指示できます。これを 1 回だけ実行してから、独自のジェスチャ レコグナイザーからデリゲートを削除します。その結果、webView を引き続きパンおよびスクロールできますが、(単一の) タップ ジェスチャは受信されなくなります。

- (void)viewDidLoad 
{      
    [super viewDidLoad];

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];

    // view is your UIViewController's view that contains your UIWebView as a subview
    [self.view addGestureRecognizer:tap];

    tap.delegate = self;
}

- (void)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer
{
    NSLog(@"tap!");

    // this is called after gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: so we can safely remove the delegate here
    if (gestureRecognizer.delegate) {
        NSLog(@"Removing delegate...");
        gestureRecognizer.delegate = nil;
    }
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if ([otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
        [otherGestureRecognizer requireGestureRecognizerToFail:gestureRecognizer];

        NSLog(@"added failure requirement to: %@", otherGestureRecognizer);
    }

    return YES;
}

楽しみ!

于 2013-09-16T18:36:15.890 に答える
3
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer {
    return YES;
}
于 2013-10-26T10:51:51.650 に答える
2

もう 1 つの方法は、透明な UIButton を UIWebView の上に置き、このボタンからのタップを処理することです。場合によっては、それが良い解決策になるかもしれません。

UIWebView webView = [UIWebView new];
//...

UIButton *transparentButton = [UIButton buttonWithType:UIButtonTypeCustom];
[transparentButton addTarget:self action:@selector(buttonTapped) forControlEvents:(UIControlEventTouchUpInside)];
transparentButton.frame = webView.frame;
transparentButton.layer.backgroundColor = [[UIColor clearColor] CGColor];
[self.view transparentButton];
于 2013-09-06T17:20:42.263 に答える
1

ここでの私の回答も役立つかもしれません。UIWebView の JavaScript でピンチ ジェスチャを処理する実際の例です。

(必要に応じて、イベントを Objective-C に戻すこともできます。こちらの回答を参照してください。)

于 2010-09-02T21:37:18.510 に答える