现在的位置: 首页 > 综合 > 正文

自定义 UIWebview 添加长按保存图片等操作

2018年04月19日 ⁄ 综合 ⁄ 共 3664字 ⁄ 字号 评论关闭

思路: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


车小松http://blog.csdn.net/mangosnow

本文遵循“署名-非商业用途-保持一致”创作公用协议

抱歉!评论已关闭.