我的编程空间,编程开发者的网络收藏夹
学习永远不晚

iOS-长截图 (学习记录)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

iOS-长截图 (学习记录)

目录

前言

长截图 —— 也就是可以截到超出屏幕的长图。在实现长图之前,我们先要了解一下iOS的绘制普通截图操作。在此基础上,来实现长截图。

iOS — 绘制截图

 UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale); [self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
  • UIGraphicsBeginImageContextWithOptions 该函数开始创建图片上下文,它有三个参数:
    size:想要渲染图片的大小尺寸
    opaque:所要创建图片的背景是否是不透明的。YES 背景则为黑色,NO 背景则为透明。
    scale:所要创建图片的缩放比例。如果设置为0 ,则和[UIScreen mainScreen].scale效果一样,随着手机屏幕分辨率改变。
  • 调用方法renderInContext:将view的layer渲染到当前的绘制的上下文中。(Renders the layer and its sublayers into the specified context.)
  • UIGraphicsGetImageFromCurrentImageContext:基于当前位图的上下文返回图像。
  • UIGraphicsEndImageContext:从堆栈顶部删除当前基于位图的图形上下文。

以上就是iOS的截图代码了。但是对于WKwebVIew(长图)来说,这个代码截不了完整的图片。因为WKwebView考虑到性能问题,并不会加载用户看不到的地方,所以会导致截图不完整。

WKWebView长截图

思路

这边先来说一下思路吧,我也是参考了网上很多实现方法总结的。我们可以看到WKWebView中有个子视图是WKScrollView。那么我们就可以通过拖动ScrollView来加载内容,与此同时截下图片。当ScrollView拖动到底之后,将全部截图拼接起来即可。

PS:当页面有悬浮栏时就会出现问题,在每一张截图中均会出现悬浮栏。目前我没有想到可以解决这个问题的方法,但思路大概是让WKwebVIew全部加载出来,然后进行截图。

实现

外部方法

/// 对WKWebView进行长截图(没有规避H5悬浮栏)/// @param webView 需要进行截图的webView/// @param completionHandler 截图完成回调 - (void)snapshotForWKWebView:(WKWebView *)webView CaptureCompletionHandler:(void (^)(UIImage * _Nonnull))completionHandler {    //1.添加遮罩层    UIView *snapshotView = [webView snapshotViewAfterScreenUpdates:YES];    snapshotView.frame = webView.frame;    [webView.superview addSubview:snapshotView];    //2.初始化数组    self.imgArr = [NSMutableArray array];    //3.进行截图操作    CGPoint savedCurrentContentOffset = webView.scrollView.contentOffset;    webView.scrollView.contentOffset = CGPointZero;    [self createSnapshotForWKWebView:webView offset:0.0 remainingOffset_y:webView.scrollView.contentSize.height comletionBlock:^(UIImage *snapshotImg) {        webView.scrollView.contentOffset = savedCurrentContentOffset;        [snapshotView removeFromSuperview];        completionHandler(snapshotImg);    }];}
  1. 为了让用户看不到我们截图滚动的操作,这里使用snapshotViewAfterScreenUpdates 方法来实现屏幕快照进行遮盖。
  2. 初始化imgArr数组,之后用来存放每一部分截图。
  3. 保存当前WKScrollView.contentOffset以便截图操作结束后还原“案发现场”。
  4. WKScrollView.contentOffset设置为CGPointZero,调用截图方法开始截图。

截图操作方法

/// 绘制WKWebView长截图/// @param webView 所需要截图的WebView/// @param offset_y 当前scollView的y偏移量/// @param reOffset_y 剩余scollView的y偏移量/// @param completeBlock 回调块- (void)createSnapshotForWKWebView:(WKWebView *)webView offset:(float)offset_y remainingOffset_y:(float)reOffset_y comletionBlock:(void(^)(UIImage *snapshotImg))completeBlock{    //判断scrollView是否已经滚动到底    if (reOffset_y>0) {        //设置        [webView.scrollView setContentOffset:CGPointMake(0, offset_y) animated:NO];        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(),^{            //对页面进行截图操作            UIGraphicsBeginImageContextWithOptions(webView.frame.size, YES, [UIScreen mainScreen].scale);            [webView.layer renderInContext:UIGraphicsGetCurrentContext()];            UIImage * img = UIGraphicsGetImageFromCurrentImageContext();            UIGraphicsEndImageContext();            //将截图添加进数组            [self.imgArr addObject:img];            //修改offsetY偏移量            CGFloat newOffset_y = offset_y + webView.scrollView.frame.size.height;            CGFloat newReOffset_y = reOffset_y - webView.frame.size.height;            [self createSnapshotForWKWebView:webView offset:newOffset_y remainingOffset_y:newReOffset_y comletionBlock:completeBlock];                    });    }else {        //合成截图为最终截图        UIView * containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, webView.frame.size.width, webView.scrollView.contentSize.height)];        CGFloat originYOfImgView = 0;        for (int i = 0; i<self.imgArr.count; i++) {            UIImageView * imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, originYOfImgView, webView.frame.size.width, webView.frame.size.height)];            UIImage * img = self.imgArr[i];            imgView.image = img;            originYOfImgView += webView.frame.size.height;            [containerView addSubview:imgView];        }        //添加合成视图        [webView.superview addSubview:containerView];        //处理最终合并截图        UIGraphicsBeginImageContextWithOptions(containerView.frame.size, YES, [UIScreen mainScreen].scale);        [containerView.layer renderInContext:UIGraphicsGetCurrentContext()];        UIImage * img = UIGraphicsGetImageFromCurrentImageContext();        UIGraphicsEndImageContext();        //移除合成视图        [containerView removeFromSuperview];        //返回截图        if (completeBlock) {            completeBlock(img);        }    }}
  1. 判断当前scrollView是否已经滚动到底部。
  2. 如果没滚动到底部,则再次设置scrollView.contentOffset到下一页进行截图。
  3. 这边给截图添加延迟,保证页面完全加载。截好的图片将放入数组。
  4. 如果scrollView已经到底部,则用一个容器视图,将所有的截图拼接并且展示。
  5. 最后再对容器视图进行截图操作,便可以得到完整的WKWebView页面截图了。

End

这个方法还是存在一定的问题,如果有大佬知道如何解决悬浮栏多次被截问题,请回复我~

来源地址:https://blog.csdn.net/qq_38863196/article/details/126361878

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

iOS-长截图 (学习记录)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android学习记录

老师心得 1.每一个页面会对应一个activity 2.每一个activity对一个XML文件 3.界面在XML文件里写 4.UI=空件+布局 5.学控件就是学属性 通用属性 layout_width,layout_height: wrap
2022-06-06

Python学习记录

文章目录(1)学习Python基础(2)初识Python数据分析(3)初学Python网络爬虫(4)研读《从零开始学Python网络爬虫》,系统学习爬虫(5)初识机器学习,研读《机器学习Python实践》(6)研读《利用Python进行数据
2023-01-31

Redis学习笔记记录

基础篇什么是Redis及快速理解Redis的使用Redis解决的问题及Redis的特性Redis的应用场景及正确安装与启动Redis配置、启动、操作、关闭及版本选择字符串使用与内部实现原理字典使用与内部实现原理列表使用与内部实现原理集合使用与内部实现原理有序集
Redis学习笔记记录
2016-01-10

Python tkinter 学习记录(

最简的形式from tkinter import *root = Tk()# 创建一个Tk实例root.wm_title("标题")# 修改标题root.mainloop()# 进入root的事件循环运行结果label标签的使用from t
2023-01-30

Python学习记录day3

Python学习记录 day3今天是银角大王武sir讲课。先回顾了上节课所学,然后讲到了面向对象思想。setset是一个无序且不重复,可嵌套的元素集合class set(object):    """    set() -> new emp
2023-01-31

Python学习记录-20160108

今日学习记录:f = open("song2", "w", encoding="UTF-8")#文件句柄,以写的模式打开文件,如果没有,就新建一个文件f.write("我爱北京天安门,")#写入语句f.write("\n天安门上太阳升.")
2023-01-31

[Python学习记录]——Hello

一直以来主要使用Java语言进行编程,开始学习Python起源于2012年亚马逊双十一购书大优惠的活动中为了补齐优惠额度,正好亚马逊给推荐《Python入门基础》一书。   一年时间过去了,书是翻了翻,看了看,心里和Java做了写比较,也没
2023-01-31

Python学习记录day2

今天,跟着Alex喝了心灵的鸡汤:Be a new gentlmen着装得体每天洗澡适当用香水女士优先不随地吐痰、不乱扔垃圾、不在人群中抽烟不大声喧哗不插队、碰到别人要说抱歉不在地铁上吃东西尊重别人的职业和劳动尊重别人隐私,不随便打听别人工
2023-01-31

python 20171115学习记录

遍历列表def travel(string): index = 0 while index < len(string): letter = string[index] print letter index = index + 1a = "1
2023-01-31

Modbus Poll学习记录

一、安装Modbus Poll 我使用的版本是:64位的9.2.2版本,如下图:   二、打开软件 界面如下(截图时我把最初系统默认打开的的那个实例关掉了): 三、新建实例 点击File-New,如下图:  点击new以后界面如下: 四、建立连接  点击:Co
Modbus Poll学习记录
2017-09-06

『爬虫』学习记录

## 在学习爬虫中遇到很多坑,写出来供道友参考出现诸如以下错误    ModuleNotFoundError: No module named 'js2xml'    NameError: name 'js2xml' is not defi
2023-01-31

详解有关Android截图与录屏功能的学习

简单的截屏和录屏功能。因为MediaProjection是5.0以上才出现的,所以今天所讲述功能实现,只在5.0以上的系统有效。截屏: 步骤如下: 1:获取MediaProjectionManager2:通过MediaProjectionM
2022-06-06

记录Android开发学习

记录Android开发学习Menu菜单学习创建菜单Menu创建主界面MainActivity设置点击事件发送数据接受数据 Menu菜单学习 1.掌握Android中菜单的创建。 2.掌握Intent信使组件。 创建菜单Menu 我们模仿微信
2022-06-06

redis 命令学习记录

杀掉客户端 CLIENT KILL TYPE normalCLIENT KILL TYPE slaveCLIENT KILL TYPE pubsub
redis 命令学习记录
2017-03-16

记录我的Python学习笔记

不想再像以前那样,什么都从头开始学习语法、总结语法,这样反而会过分纠结于语法,耽误了开发,毕竟语言的主要属性是工具,次要的属性是语言本身。所以还是先熟练使用语言去进行开发,等足够熟悉了,再去研究语言本身(编译原理……)。另外对于算法、设计模
2023-01-31

Python学习记录-paramiko模

[TOC]paramiko模块基于SSH用于连接远程服务器并执行相关操作。1. SSHClient用于连接远程服务器并执行基本命令基于用户名密码连接:import paramiko# 创建SSH对象ssh = paramiko.SSHCli
2023-01-31

HTML语法学习笔记:记录您的学习之旅

学习 HTML 语法的全面指南,从基础知识到高级概念,帮助您记录您的学习之旅,并创建出色的网络内容。
HTML语法学习笔记:记录您的学习之旅
2024-03-09

编程热搜

目录