WebView截图的一种思路

网页完整截图的方法

那天想起来一个APP分享的时候生成一张长图,想试一下,开始想的很简单:在webview加载完成的delegate里面,获取scroll view的layer,然后根据图形上下文获取image,保存相册即可.然而,失败了╮(╯▽╰)╭

第一种方法:更改scroll view的frame再截图

上面之所以无法截图,是因为scroll view的layer的实际需要截图的layer不是同一个东西,还没有加载出来的页面并没有显示在layer上?所以,只要改变scroll view的frame,使content size和frame的size一样就好了.核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (UIImage *)captureScrollView:(UIScrollView *)scrollView{
UIImage* image = nil;
UIGraphicsBeginImageContextWithOptions(scrollView.contentSize, NO, [UIScreen mainScreen].scale);
CGPoint originalContentOffset = scrollView.contentOffset;
CGRect originalFrame = scrollView.frame;
scrollView.contentOffset = CGPointZero;
scrollView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height);
[scrollView.layer renderInContext: UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
scrollView.contentOffset = originalContentOffset;
scrollView.frame = originalFrame;
return image ? image : nil;
}

KVC获取web view私有容器变量

web view是一个看起来简单,内部复杂的控件,获取一下私有变量列表,会发现有一个_internal私有变量,type是UIWebViewInternal,然后在iOS runtime headers可以看到这个类,点击这里,继续查看这个类的ivar list,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name:scroller------type:@"UIScrollView"
name:browserView------type:@"UIWebBrowserView"
name:checkeredPatternView------type:@"UICheckeredPatternView"
name:delegate------type:@"<UIWebViewDelegate>"
name:scalesPageToFit------type:b1
ame:isLoading------type:b1
name:hasOverriddenOrientationChangeEventHandling------type:b1
name:drawsCheckeredPattern------type:b1
name:webSelectionEnabled------type:b1
name:drawInWebThread------type:b1
name:inRotation------type:b1
name:didRotateEnclosingScrollView------type:b1
name:request------type:@"NSURLRequest"
name:clickedAlertButtonIndex------type:q
name:webViewDelegate------type:@"UIWebViewWebViewDelegate"
name:pdfHandler------type:@"UIWebPDFViewHandler"

好了,通过Xcode可以看到,进行web view内容显示的就是UIWebBrowserView这个类,接下来就好办了,直接上代码:

1
2
3
4
5
6
7
// web view loading success
UIView *browser = [webView valueForKeyPath:@"_internal.browserView"];
UIImage* image = nil;
UIGraphicsBeginImageContextWithOptions(browser.layer.frame.size, NO, [UIScreen mainScreen].scale);
[browser.layer renderInContext: UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

KVC大法好!QAQ~