UIWebView
のサブクラスを作成し、touchesBegan
、touchesMoved
、およびtouchesEnded
メソッドを実装しました。
ただし、webviewサブクラスはtouch
イベントを処理していません。
UIWebView
サブクラス内のタッチイベントを処理する方法はありますか?
サブクラス化は不要で、単に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;
}
必要なのがジェスチャーを処理することだけで、残りの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」で、準備完了です...
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ビュー上にある必要があります。
これがあなたが望むものかどうかはわかりません(あなたが求めたものではありませんが、あなたのエンドゲームが何であるかによって動作するかもしれません)、代わりに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(/* ... */);"];
}
お役に立てれば?
UIWebViewでのジェスチャの処理については、 this Apple開発者フォーラムスレッド で説明しています。
そこに提供された情報を使用すると、ほとんどまたはすべての場合に追加のビューは必要ありません。前述のように、UIWebViewをオーバーライドする方法はありません。
スレッド内の最も重要な投稿のコピーペースト:
これは既知の問題です。 UIWebViewには独自のUITapGestureRecognizersがあり、UIWebView自体のプライベートサブビュー上にあります。 UIGestureRecognizerの優先順位は、ビュー階層のより深いビューにアタッチされたジェスチャがスーパービューのジェスチャを除外するように定義しているため、Webビューのタップジェスチャは常にあなたの勝ちです。
Webビューの通常のタップと一緒にタップを許可する場合は、UIGestureRecognizerDelegateメソッドのジェスチャーRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizerを実装し、他のタップジェスチャーに対してYESを返すことが最善の解決策です。この方法では、タップハンドラーが呼び出されますが、Webビューは引き続き呼び出されます。
タップを処理する唯一の人である必要がある場合、UITapGestureRecognizerをサブクラス化してUIGestureRecognizerSubclass.hで一方向のオーバーライドを使用できるようにする必要があります。その後、canBePreventedByGestureRecognizerからNOを返すことができます。あなたを防ぐことができます。
いずれにせよ、私たちはこれについて知っており、将来それをより簡単にすることを望んでいます。
UIWebViewは、ビュー領域(ハイパーリファレンス、または特別に処理する必要のある他の領域ではない)をタップすると、- (void)webViewDidNotClick: (id)webBrowserView
セレクターに応答するかどうかを確認することがわかりました。そのため、そのセレクターを処理コードで実装できます:)
UIWindowで-sendEvent:をオーバーライドして、これらのタッチイベントをインターセプトできるかどうかを確認します。
独自のタップを検出したいが、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';"];
}
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
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];
}
お役に立てば幸いです!