uigesturerecognizerはuiwebviewで動作しますか?
-
04-10-2019 - |
質問
uiscrollviewのサブビューであるuiwebviewを使用してuigesturerecognizerを使用しようとしています。これは奇妙に聞こえますが、私が持っているとき numberOfTouchesRequired
セレクターの火災を2つに設定しますが、いつ numberOfTouchesRequired
セレクターが発射しない1つに設定されています。
これが私のコードです:
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
}
AppleサンプルをUigesturerCognizerに使用し、ペン先にWebViewを挿入することでこれを確認しました。タップコードは、WebViewの領域内で至る所で機能します。
解決
私が見たことから、Uiwebviewは他の人とうまくいきません。ジェスチャー認識者の場合、次のようにyesを返してみてください。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
私は3.0と後方互換性がなければならなかったので、UIWebview内のJavaScriptを使用してすべてのジェスチャー処理を行うことになりました。良い解決策ではありませんが、私のニーズのために機能しました。要素を長いプレスをキャプチャし、タップ、スワイプ、ピンチ、回転をキャプチャすることができました。もちろん、私はローカルコンテンツのみを使用していました。
編集:
あなたは見ることができます 電話ガップ Uiwebviewの代表者にメッセージを送信する例については。一言で言えば、使用します 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;
}
}
電話ガップコードで、メッセージを送信するためにキューとタイマーを設定していることがわかります。使用法に応じて、同じことをする必要があるかもしれません。このトピックには他の質問があります。
これが次のとおりです イベント処理 ドキュメンテーション。私の場合、イベントリスナーを追加しました 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 );
};
実際のイベント処理は、ニーズに大きく依存します。各イベントハンドラーはaを受け取ります TouchEvent 各アイテムがaのタッチプロパティで 触る. 。 Touchstartハンドラーに開始時間と場所を記録できます。タッチが遠くに移動するか、間違った時間が経過した場合、それは長いタッチではありません。
WebKitは、選択を開始してコピーするために長いタッチを処理しようとする場合があります。イベントハンドラーで使用できます event.preventDefault();
デフォルトの動作を停止します。私も見つけました -webkit-user-select:none
CSSプロパティがいくつかのことに便利です。
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には、リンクを超えてインタラクティブな要素がありませんでした。
他のヒント
Uiwebviewには独自のプライベートビューがあり、ジェスチャー認識者も添付されています。したがって、優先順位ルールは、UIWebviewに適切に動作しないように、ジェスチャー認識者を追加します。
1つのオプションは、uigesturerecognizerdelegateプロトコルを実装し、メソッドGestureRecognizerを実装することです。他のタップジェスチャーについては、この方法から「はい」を返します。これにより、タップハンドラーが呼び出されますが、Webビューは引き続き呼び出されます。
これはややハックっぽいソリューションですが、機能します。 uiwebviewには、プライベートAPIを使用せずに通常アクセスできない内部ジェスチャー認識者がたくさんあります。ただし、実装すると無料で入手できます gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
. 。その時点で、すべての内部UITAPGESTURERECOUGNIASERSが、あなた自身のUITAPGESTURERECOGNIZERが失敗した場合にのみ発射するように指示できます。あなたはそれを一度だけしてから、あなた自身のジェスチャー認識者からデリゲートを削除します。その結果、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;
}
楽しみ!
私は同じ問題を抱えていました。このソリューションは私のために機能しました:
1)インターフェイスにプロトコルを追加してください:uigesturerecognizerdelegateたとえば:
@interface ViewController : UIViewController <SlideViewProtocol, UIGestureRecognizerDelegate>
2)このコード行を追加します
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES
}
3)ジェスチャーをセットアップします
UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(nextSlide)];
swipeGesture.numberOfTouchesRequired = 1;
swipeGesture.direction = (UISwipeGestureRecognizerDirectionLeft);
swipeGesture.cancelsTouchesInView = YES; [swipeGesture setDelegate:self];
[self.view addGestureRecognizer:swipeGesture];
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer {
return YES;
}
もう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];