一、我們要做什么
我們要做的是這種效果!
打開一個網頁,百度為例吧
這個時候我們點擊保存截圖,我們要把整個網頁保存為圖片,然后在網頁的結尾加上一個二維碼,這樣分享到微信什么的,就可以直接識別網頁鏈接了。效果是醬嬸兒的。
二、需要哪些知識點
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不支持屏幕旋轉,就可以省去了。