时间:2021-05-19
前言
同时按下 Home 键和电源键,咔嚓一声,就得到了一张手机的截图,这操作想必 iPhone 用户再熟悉不过了。我们作为研发人员,面对的是一个个的 View,那么该怎么用代码对 View 进行截图呢?
这篇文章主要讨论的是如何在包括 UIWebView 和 WKWebView 的网页中进行长截图,对应的示例代码在这儿:https://github.com/VernonVan/PPSnapshotKit(本地下载) 。
UIWebView 截图
对 UIWebView 截图比较简单,renderInContext 这个方法相信大家都不会陌生,这个方法是 CALayer 的一个实例方法,可以用来对大部分 View 进行截图。我们知道,UIWebView 承载内容的其实是作为其子 View 的 UIScrollView,所以对 UIWebView 截图应该对其 scrollView 进行截图。具体的截图方法如下:
- (void)snapshotForScrollView:(UIScrollView *)scrollView{ // 1. 记录当前 scrollView 的偏移和位置 CGPoint currentOffset = scrollView.contentOffset; CGRect currentFrame = scrollView.frame; scrollView.contentOffset = CGPointZero; // 2. 将 scrollView 展开为其实际内容的大小 scrollView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height); // 3. 第三个参数设置为 0 表示设置为屏幕的默认缩放因子 UIGraphicsBeginImageContextWithOptions(scrollView.contentSize, YES, 0); [scrollView.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // 4. 重新设置 scrollView 的偏移和位置,还原现场 scrollView.contentOffset = currentOffset; scrollView.frame = currentFrame;}WKWebView 截图
虽然 WKWebView 里也有 scrollView,但是直接对这个 scrollView 截图得到的是一片空白的,具体原因不明。一番 Google 之后可以看到好些人提到 drawViewHierarchyInRect 方法, 可以看到这个方法是 iOS 7.0 开始引入的。官方文档中描述为:
Renders a snapshot of the complete view hierarchy as visible onscreen into the current context.
注意其中的 visible onscreen,也就是将屏幕中可见部分渲染到上下文中,这也解释了为什么对 WKWebView 中的 scrollView 展开为实际内容大小,再调用 drawViewHierarchyInRect 方法总是得到一张不完整的截图(只有屏幕可见区域被正确截到,其他区域为空白)。
不过,这样倒是给我们提供了一个思路,可以将 WKWebView 按屏幕高度裁成 n 页,然后将 WKWebView 一页一页的往上推,每推一页就调用一次 drawViewHierarchyInRect 将当前屏幕的截图渲染到上下文中,最后调用 UIGraphicsGetImageFromCurrentImageContext 从上下文中获取的图片即为完整截图。
核心代码如下(代码为演示用途,完整代码请从这里(本地下载) 查看):
- (void)snapshotForWKWebView:(WKWebView *)webView{ // 1 UIView *snapshotView = [webView snapshotViewAfterScreenUpdates:YES]; [webView.superview addSubview:snapshotView]; // 2 CGPoint currentOffset = webView.scrollView.contentOffset; ... // 3 UIView *containerView = [[UIView alloc] initWithFrame:webView.bounds]; [webView removeFromSuperview]; [containerView addSubview:webView]; // 4 CGSize totalSize = webView.scrollView.contentSize; NSInteger page = ceil(totalSize.height / containerView.bounds.size.height); webView.scrollView.contentOffset = CGPointZero; webView.frame = CGRectMake(0, 0, containerView.bounds.size.width, webView.scrollView.contentSize.height); UIGraphicsBeginImageContextWithOptions(totalSize, YES, UIScreen.mainScreen.scale); [self drawContentPage:0 maxIndex:page completion:^{ UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // 8 [webView removeFromSuperview]; ... }];}- (void)drawContentPage(NSInteger)index maxIndex:(NSInteger)maxIndex completion:(dispatch_block_t)completion{ // 5 CGRect splitFrame = CGRectMake(0, index * CGRectGetHeight(containerView.bounds), containerView.bounds.size.width, containerView.frame.size.height); CGRect myFrame = webView.frame; myFrame.origin.y = -(index * containerView.frame.size.height); webView.frame = myFrame; // 6 [targetView drawViewHierarchyInRect:splitFrame afterScreenUpdates:YES]; // 7 if (index < maxIndex) { [self drawContentPage:index + 1 maxIndex:maxIndex completion:completion]; } else { completion(); }}代码注意项如下(对应代码注释中的序号):
注意:我们的截图方法中有对 webView 的 frame 进行操作,如果其他地方如果有对 frame 进行操作的话,是会影响我们截图的。所以在截图时应该禁用掉其他地方对 frame 的改变,就像这样:
- (void)layoutWebView{ if (!_isCapturing) { self.wkWebView.frame = [self frameForWebView]; }}结语
当前 WKWebView 的使用越来越广泛了,我随意查看了内存占用:打开同样一个网页,UIWebView 直接占用了 160 MB 内存,而 WKWebView 只占用了 40 MB 内存,差距是相当明显的。如果我们的业务中用到了 WKWebView 且有截图需求的话,那么还是得老老实实完成的。
最后,本文对应的代码在这儿:https://github.com/VernonVan/PPSnapshotKit(本地下载)
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
你知道什么是无主商标吗?无主商标有哪些特征?如何为无主商标找到“主人”?今天,小编就和大家聊聊关于无主商标的那些事儿,一起长知识啦!1.?无主商标无主商标是指由
mac电脑系统截图名日期后缀去除方法来啦!玩mac电脑的朋友应该知道默认情况下,在osx中用Command-Shift-3等快捷键来截图时,你会发现生成的图
很多人都认为iOS8已经够够强大了,没有什么越狱的必要。如果你看了近段时间那些更新支持iOS8的越狱插件,你就会知道自己的太无知了。接下来小编就为大家盘点一下1
刚接手的店铺应该怎么开始?新开的店铺应该如何优化?废店应该如何重获新生?我总结了最近几篇文章的反馈,发现非常多的人很关注前面的几个问题。今天还是讲运营那些事儿!
看了一些你下面的回答和追问。你说你还在学校,那就应该知道,怎么变也是离不回开架构的,那就是规则答。你应该熟悉那些先。然后就是建议你还是专攻推广方面的(网店的构成