新しい答え:
これが私たちが望んでいるもののようです。
https://stackoverflow.com/a/3198220/700471
古い答え:
さて、いくつかの調査の後、これが取引です:
あなたの質問で説明したことは正確に思えます:
まず第一に、標準のコンテキスト メニューのデフォルトのメニュー項目にメニュー項目を追加することはできません。ただし、特定の CSS プロパティを使用してコンテキスト メニューをオフにすることができます。したがって、解決策は、デフォルトのメニューをオフにして、独自のメニューを最初から実装することです。独自のコンテキスト メニューを実装するには、最初にタブ アンド ホールド ジェスチャをキャッチし、画面上の指の座標を取得し、これらの座標を Web ページの座標系に変換し、最後に HTML 要素を探す必要があります。この場所。
つまり、コンテキスト メニューを使用して独自のポップオーバー コントローラーを実装することを計画しています。
あなたの質問のように見えるのは、UIWebView でロングタップ ジェスチャを取得し、それを Web ページの座標に変換して、選択された DOM 要素を見つけ、それをポップオーバーを生成するコンテキストとして使用する方法です。メニュー。
私が見つけたのはthis、具体的には次のコード行でした:
NSString *js = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).innerHTML", touchPoint.x, touchPoint.y];
これは、どの要素が長押しされたかを把握するために必要な JS のように見えます。もちろん、それがリンクであるかどうかを確認し、そこからコンテキスト メニューを実行するために、いくつかの図形を実行する必要がありますが、そうではありません。私が調べたもの。
いくつかのさらなる考え:
おそらく最も簡単な方法はUILongPressGestureRecognizer
、 を UIWebView にアタッチし (ペン先で簡単に実行できます)、「送信済みアクション」が ViewController の適切な IBAction を指していることを確認することです。(デリゲート アウトレットも使用できると思いますが、その必要はありませんでした。)
いずれにせよ、ジェスチャー認識エンジンの locationOfTouch:inView: メソッドを使用できます。おそらく使用したいビューは、UIWebView のコンテンツ ビューになります。myWebView.scrollView.subviews[0]
新しい配列インデックス添え字を使用していません)。
とにかく、私はあなたの質問に答えるのに十分な情報を提供したと思います.
編集:
さて、あなたはまだこれで問題を抱えているので、テストプロジェクトを作成して動作させました. これに関して少し面倒なことの 1 つは、WebKit がどういうわけか DOM 内のオブジェクトの周りに「バッファー」領域を追加することです。つまり、リンクの横に少し触れるとハイライトされますが、JS コマンドを使用するとハイライトさelementFromPoint
れません。そのため、この方法を使用してポップアップをトリガーするには、より慎重に触れる必要があります。しかし、それは機能します。
「シングルビュー」テンプレートを使用して空のプロジェクトを作成UIWebView
し、xib に a を投げて、そのdelegate
アウトレットをファイルの所有者に向けました。次にUILongPressGestureRecognizer
、UIWebView にアタッチされた xib に a を入れます。これdelegate
をファイルの所有者として設定し、そのselector
アウトレットをlongPressDetected
ファイルの所有者の IBAction に設定しました。また、Interface Builder のレコグナイザーのプロパティで [ビューでキャンセル] のチェックを外しました。
ビューコントローラーのコードは次のとおりです。
インターフェース:
//
// WVTViewController.h
// WebViewTest
//
#import <UIKit/UIKit.h>
@interface WVTViewController : UIViewController <UIWebViewDelegate, UIGestureRecognizerDelegate>
@property (nonatomic, weak) IBOutlet UIWebView *myWebView;
@property (nonatomic) BOOL didFirstLoad;
- (IBAction)longPressDetected:(id)sender;
@end
実装:
//
// WVTViewController.m
// WebViewTest
//
#import "WVTViewController.h"
@interface WVTViewController ()
@end
@implementation WVTViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Just load google.
NSURL *theURL = [NSURL URLWithString:@"http://www.google.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:theURL];
[self.myWebView loadRequest:request];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
if (!self.didFirstLoad) {
// Disable the default contextual menu.
[webView stringByEvaluatingJavaScriptFromString:@"document.body.style.webkitTouchCallout='none';"];
}
}
// Called by the gesture recognizer.
- (IBAction)longPressDetected:(UILongPressGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateBegan) {
NSLog(@"Long press detected.");
CGPoint webViewCoordinates = [sender locationInView:self.myWebView];
NSLog(@"WebView coordinates are: %@", NSStringFromCGPoint(webViewCoordinates));
// Find the DOM element
NSString *locatorString = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).innerHTML", webViewCoordinates.x, webViewCoordinates.y];
NSString *result = [self.myWebView stringByEvaluatingJavaScriptFromString: locatorString];
NSLog(@"Element Found: %@", result);
}
}
// Necessary or the gesture recognizer won't call the IBAction.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
@end
私が言ったように、私は上記のコードをテストしましたが、うまくいきました。もちろん、JS を変更して、またはinnerHTML
など、以外のものを使用することもできます。DOM オブジェクトを JSON 文字列化して Objective-C に戻し、ネイティブ オブジェクトに変換し、その環境でチェックを実行してください。しかし、私は JS の専門家ではないので、それを調査するつもりはありません。tagName
href
elementFromPoint
ちなみに、機能する座標が UIWebView 自体のタッチ座標であることに少し驚きました。私はコードのブロック全体を調整してmyWebView.scrollView.subviews
コンテンツ ビューを見つけ、そのビューを呼び出しlocationOfTouch:inView:
ました。しかし、私はファンキーな動作をしていたので、直感で webview 座標を使用すると、横にスクロールしたり下にスクロールしたときに大きな Web ページでも問題なく動作しました。Apple がプログラムした webview 内のある種の動作が、これらの座標を変換する可能性があると思われます。おそらく、JS の座標系は、コンテンツ ビューがスクロールビュー内で移動する方法に基づいて変更されます。これは、私にとって最も理にかなっています。