web-dev-qa-db-ja.com

UIWebview内のタッチの処理

UIWebViewのサブクラスを作成し、touchesBegantouchesMoved、およびtouchesEndedメソッドを実装しました。

ただし、webviewサブクラスはtouchイベントを処理していません。

UIWebViewサブクラス内のタッチイベントを処理する方法はありますか?

35
Biranchi

サブクラス化は不要で、単にUITapGestureRecognizerを追加します:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapMethod)];
[tap setNumberOfTapsRequired:1]; // Set your own number here
[tap setDelegate:self]; // Add the <UIGestureRecognizerDelegate> protocol

[self.myWebView addGestureRecognizer:tap];

<UIGestureRecognizerDelegate>プロトコルをヘッダーファイルに追加し、次のメソッドを追加します。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}
45
John

必要なのがジェスチャーを処理することだけで、残りのUIWebView機能をそのままにした場合、UIWebViewをサブクラス化してこの戦略を使用できます。

uIWebViewサブクラスのinitメソッドで、ジェスチャーレコグナイザーを追加します。例:

UISwipeGestureRecognizer  * swipeRight = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeGestureRightMethod)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[self addGestureRecognizer:swipeRight];
swipeRight.delegate = self;

次に、このメソッドをクラスに追加します。

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

指定されたセレクターをクラスに追加して処理します。この場合は「handleSwipeGestureRightMethod」で、準備完了です...

8
ecume des jours

UIViewの上にUIWebViewを配置し、touchesDidBeginなどをオーバーライドしてから、それらをWebビューに送信できます。例:

ユーザーがUIViewに触れると、

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{  
    // Execute your code then send a touchesBegan to your webview like so:
[webView touchesBegan:touches withEvent:event];
return;
}

UIViewはWebビュー上にある必要があります。

7

これがあなたが望むものかどうかはわかりません(あなたが求めたものではありませんが、あなたのエンドゲームが何であるかによって動作するかもしれません)、代わりにUIWebView内からJavaScriptのタッチを解釈し、行う

document.location='http://null/'+xCoord+'/'+yCoord; // Null is arbitrary.

その後、UIWebViewのデリゲートメソッドを使用してそれをキャッチできます

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

そして、request.URL.Host(またはそれが何であれ)isEqualToString:@ "null"が関連するアクションを実行する場合(そしてYESの代わりにNOを返す)。次のような操作を行うことで、各ページにJSを追加することもできます。

- (void)webViewDidFinishLoad:(UIWebView *)webView {
  [webView stringByEvaluatingJavaScriptFromString:@"window.ontouchstart=function(/* ... */);"];
}

お役に立てれば?

5
Benjie

UIWebViewでのジェスチャの処理については、 this Apple開発者フォーラムスレッド で説明しています。

そこに提供された情報を使用すると、ほとんどまたはすべての場合に追加のビューは必要ありません。前述のように、UIWebViewをオーバーライドする方法はありません。

スレッド内の最も重要な投稿のコピーペースト:

これは既知の問題です。 UIWebViewには独自のUITapGestureRecognizersがあり、UIWebView自体のプライベートサブビュー上にあります。 UIGestureRecognizerの優先順位は、ビュー階層のより深いビューにアタッチされたジェスチャがスーパービューのジェスチャを除外するように定義しているため、Webビューのタップジェスチャは常にあなたの勝ちです。

Webビューの通常のタップと一緒にタップを許可する場合は、UIGestureRecognizerDelegateメソッドのジェスチャーRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizerを実装し、他のタップジェスチャーに対してYESを返すことが最善の解決策です。この方法では、タップハンドラーが呼び出されますが、Webビューは引き続き呼び出されます。

タップを処理する唯一の人である必要がある場合、UITapGestureRecognizerをサブクラス化してUIGestureRecognizerSubclass.hで一方向のオーバーライドを使用できるようにする必要があります。その後、canBePreventedByGestureRecognizerからNOを返すことができます。あなたを防ぐことができます。

いずれにせよ、私たちはこれについて知っており、将来それをより簡単にすることを望んでいます。

3
ecotax

UIWebViewは、ビュー領域(ハイパーリファレンス、または特別に処理する必要のある他の領域ではない)をタップすると、- (void)webViewDidNotClick: (id)webBrowserViewセレクターに応答するかどうかを確認することがわかりました。そのため、そのセレクターを処理コードで実装できます:)

2
indexless

UIWindowで-sendEvent:をオーバーライドして、これらのタッチイベントをインターセプトできるかどうかを確認します。

0
Unfalkster

独自のタップを検出したいが、UIWebViewのタップを無効にする場合は、私のソリューションを使用できます。

-(void)recursivelyDisableTapsOnView:(UIView*)v{
    for(UIView* view in v.subviews){
        for(UIGestureRecognizer* g in view.gestureRecognizers){
            if(g == self.ownTapRecognizer){
                continue;
            }
            if([g isKindOfClass:[UITapGestureRecognizer class]] ||
               [g isKindOfClass:[UILongPressGestureRecognizer class]] ||
               [g isKindOfClass:NSClassFromString(@"UITapAndAHalfRecognizer")]){
                g.enabled = NO;
            }
        }
        [self recursivelyDisableTapsOnView:view];
    }
}


- (void)webViewDidFinishLoad:(UIWebView *)webView{
    [self recursivelyDisableTapsOnView:webView];

    //disable selection
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
    // Disable callout
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
}
0
malhal

TouchesBegan、touchesMoved、touchesEndedが呼び出されたときにサブクラスの実装が呼び出されないということですか?

オブジェクトのインスタンスの作成方法に問題があるようです。もっと詳細が必要だと思います。

(フォームのコメントを取得)

ヘッダーファイル

#import <UIKit/UIKit.h> 

@interface MyWebView : UIWebView { } @end 

実装ファイル

#import "MyWebView.h" 

@implementation MyWebView 

- (id)initWithFrame:(CGRect)frame { 
    if (self = [super initWithFrame:frame]) { } return self; 
} 

- (void)drawRect:(CGRect)rect { 
    NSLog(@"MyWebView is loaded"); 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
   NSLog(@"touches began"); 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    NSLog(@"Touches ended");     
} 

- (void)dealloc { 
   [super dealloc]; 
} 

@end
0
rjstelling

Unfalksterの発言に続いて、hitTestメソッドを使用して目的を達成できますが、UIWindowをサブクラス化する必要はありません。これをWebビューのサブクラスに配置するだけです。コンパイル時に警告が表示されますが、動作します:

- (void)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (event.type == UIEventTypeTouches) {

        // get location info
        CGFloat x = point.x;
        CGFloat y = point.y;

        // get touches
        NSSet *touches = [event allTouches];

        // individual touches
        for (UITouch *touch in touches) {

            if (touch.phase == UITouchPhaseBegan) {
                // touches began

            } else if (touch.phase == UITouchPhaseMoved) {

            }

            // etc etc
        }
    }

    // call the super
    [super hitTest:point withEvent:event];
}

お役に立てば幸いです!

0
imnk