一、我们要做什么
我们要做的是这种效果!
打开一个网页,百度为例吧
webView展示网页内容
这个时候我们点击保存截图,我们要把整个网页保存为图片,然后在网页的结尾加上一个二维码,这样分享到微信什么的,就可以直接识别网页链接了。效果是酱婶儿的。
相册中查看保存的图
二、需要哪些知识点
1、主要还是绘图
2、二维码
3、如果想做成home+power截屏时保存这张大长图,还要用到截屏的通知,这个最后说吧。
三、Let's 整!
第一页第一页就不说了,storyboard上拖个输入框、按钮什么的就ok了。
输入网址,点击确定后传给第二个页面的webView去请求链接,展示网页。
展示之后,我们要把整个网页全部绘制成图片。
下面是保存截图按钮执行的代码
- (IBAction)saveAction:(id)sender {
// 获取scrollView
UIScrollView *scrollView = self.webView.scrollView;
UIImage* image = nil;
// 开始绘制
UIGraphicsBeginImageContextWithOptions(CGSizeMake(scrollView.contentSize.width, scrollView.contentSize.height+100), NO, 0.0);
{
// 保存原有的scrollView偏移量和frame
CGPoint savedContentOffset = scrollView.contentOffset;
CGRect savedFrame = scrollView.frame;
// 展开scrollView
scrollView.contentOffset = CGPointZero;
scrollView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height);
// 将scrollView的layer渲染到上下文中
[scrollView.layer renderInContext: UIGraphicsGetCurrentContext()];
// 画背景
UIImage *backImage = [UIImage createImageWithColor:[UIColor whiteColor]];
[backImage drawInRect:CGRectMake(0, scrollView.contentSize.height-100, scrollView.contentSize.width, 100)];
// 画二维码
UIImage *qrImage = [QRCodeGenerator qrImageForString:self.url imageSize:300];
[qrImage drawInRect:CGRectMake(scrollView.contentSize.width*0.5-40, scrollView.contentSize.height-100+10, 80, 80)];
// 获取结果图片
image = UIGraphicsGetImageFromCurrentImageContext();
// 还原scrollView偏移量和frame
scrollView.contentOffset = savedContentOffset;
scrollView.frame = savedFrame;
}
UIGraphicsEndImageContext();
if (image != nil) {
// 写到相册
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}
}
讲解下原理:主要就是让webView的frame中的宽高等于自己的contentSize的宽高,这样webView就把自己的所有内容展示出来了,然后把webView的layer渲染到上下文中,再通过如下的库生成二维码图片(头文件QRCodeGenerator.h),再将二维码绘制到刚才的layer上。文字、图片什么的都可以这样绘制上去。最后再从上下文中获取绘制好的最后的图片,通过UIImageWriteToSavedPhotosAlbum方法,可以将图片保存到相册。
生成二维码的库
灰常简单就实现了。
三、拓展
这时如果说想用截屏来做的话,那就可以使用如下的通知来获取截屏事件。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(screenShot:) name:UIApplicationUserDidTakeScreenshotNotification object:nil];
关于图像上下文,绘图中比较难理解的还是图形上下文,很多人应该不理解为什么上下文就突然出现在这里了,它是做什么用的?这时看看下面这两篇就差不多可以理解的差不多了。
上下文是什么,了解上下文是什么、干嘛用的
iOS绘图上下文的理解,这样就了解了上下文栈是干什么的,配合上面的文章就知道上下文的原理和用途了。
顺便,tableView、collectionView什么的,都是继承自ScrollView的,所以都可以用以上方法进行处理,其他的各种控件,拿到layer也都可以渲染出来保存为图片,截屏也就很方便了。下面贴下,截取显示屏幕的方法
CGSize imageSize = CGSizeZero;
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (UIInterfaceOrientationIsPortrait(orientation))
imageSize = [UIScreen mainScreen].bounds.size;
else
imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
CGContextSaveGState(context);
CGContextTranslateCTM(context, window.center.x, window.center.y);
CGContextConcatCTM(context, window.transform);
CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
if (orientation == UIInterfaceOrientationLandscapeLeft)
{
CGContextRotateCTM(context, M_PI_2);
CGContextTranslateCTM(context, 0, -imageSize.width);
}
else if (orientation == UIInterfaceOrientationLandscapeRight)
{
CGContextRotateCTM(context, -M_PI_2);
CGContextTranslateCTM(context, -imageSize.height, 0);
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
CGContextRotateCTM(context, M_PI);
CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
}
if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)])
{
[window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
}
else
{
[window.layer renderInContext:context];
}
CGContextRestoreGState(context);
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
主要思想还是获取当前window,渲染他的layer,同时对屏幕的旋转情况做了处理,如果app不支持屏幕旋转,就可以省去了。
网友评论