自定義 UIWebview 新增長按儲存圖片等操作
阿新 • • 發佈:2019-01-08
思路:safari 自帶了長按儲存的功能,分析這個功能的特點: 長按一個圖片,儲存後的圖片就是所點選的圖片,做到了精確定位。JS可以處理精確定位的問題,使用UIWebview 和 JS 能夠解決我們的問題。
直接上程式碼
UIWebView *aWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height)]; aWebView.delegate = self; aWebView.scalesPageToFit = YES; self.mainWebView = aWebView; [self.view addSubview:aWebView]; NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://image.baidu.com/"] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:20]; [self.mainWebView loadRequest:request]; UILongPressGestureRecognizer *longtapGesture = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longtap:)]; [self.view addGestureRecognizer:longtapGesture];
新增webview,新增長按手勢,看起來沒有什麼。
-(void)longtap:(UILongPressGestureRecognizer * )longtapGes{ if (longtapGes.state == UIGestureRecognizerStateBegan) { CGPoint pt = [longtapGes locationInView:self.view]; pt= [self.mainWebView convertPoint:pt fromView:nil]; CGPoint offset = [self.mainWebView.scrollView contentOffset]; CGSize viewSize = [self.view frame].size; CGSize windowSize = [self.view frame].size; CGFloat f = windowSize.width / viewSize.width; pt.x = pt.x * f + offset.x; pt.y = pt.y * f + offset.y; [self openContextualMenuAt:pt]; } }
注意看下這段程式碼
pt 為對映在webview 上的座標
得到座標後,根據contentOffset,獲取到點選的座標上在 web 絕對位置上的座標點。
test1.txt 內容如下- (void)openContextualMenuAt:(CGPoint)pt { NSString *path = [[NSBundle mainBundle] pathForResource:@"test1" ofType:@"txt"]; NSString *jsCode = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; [self.mainWebView stringByEvaluatingJavaScriptFromString: jsCode]; NSString *tags = [self.mainWebView stringByEvaluatingJavaScriptFromString: [NSString stringWithFormat:@"MyAppGetHTMLElementsAtPoint(%i,%i);",(NSInteger)pt.x,(NSInteger)pt.y]]; UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"Contextual Menu" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:nil]; if ([tags rangeOfString:@",A,"].location != NSNotFound) { [sheet addButtonWithTitle:@"開啟連結"]; } if ([tags rangeOfString:@",IMG,"].location != NSNotFound) { NSString *str = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", pt.x, pt.y]; NSString *imgStr= [self.mainWebView stringByEvaluatingJavaScriptFromString: str]; NSLog(@"啟動一個request下載圖片:%@",imgStr); [sheet addButtonWithTitle:@"儲存圖片"]; } [sheet addButtonWithTitle:@"在Safari中開啟"]; [sheet showInView:self.view]; }
function MyAppGetHTMLElementsAtPoint(x,y) {
var tags = ",";
var e = document.elementFromPoint(x,y);
while (e) {
if (e.tagName) {
tags += e.tagName + ',';
}
e = e.parentNode;
}
return tags;
}
這段js 能夠返回 web 內容座標對應 web 節點
然後通過注入方式呼叫js,並獲取到圖片地址
NSString *str = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", pt.x, pt.y];
NSString *imgStr= [self.mainWebView stringByEvaluatingJavaScriptFromString: str];
到這裡,我們的任務已經完成了大半了。
還需要做的是彈出選擇框,使用者選擇操作,程式碼實現選擇操作。此處省略若干程式碼和說明。
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
// 這裡實際啟動request,下載圖片
// 我看見UC 瀏覽器斷網也是可以下載圖片的,我大概知道是通過JS,但具體操作就不知道了,有沒有人知道是怎麼實現的,分享下
}
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
}
這裡 webview 一旦載入完成了,通過JS注入,這段js 直接去除了點選和選中效果,否則會出現uiwebview 自帶copy 工具,以及選中變灰的效果。
總結:
在webview 載入完成之後,禁用掉webview自帶的選擇和長按事件。
在外部新增長按事件,並對映成webview中長按事件所處的位置px
在通過呼叫stringByEvaluatingJavaScriptFromString:@""方法獲取到上步中px所處位置的 html 節點
同樣通過呼叫stringByEvaluatingJavaScriptFromString:@""方法得到節點的 src 資訊
新開請求去獲得圖片
我看見UC 瀏覽器斷網也是可以下載圖片的,我大概知道是通過JS,但具體操作就不知道了,有沒有人知道是怎麼實現的,分享下
DEMO下載地址:https://github.com/chexsong/WorkingDemos