1. 程式人生 > >自定義 UIWebview 新增長按儲存圖片等操作

自定義 UIWebview 新增長按儲存圖片等操作

思路: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 絕對位置上的座標點。
- (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];
}
test1.txt 內容如下
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