截取ScrollView中的全部內容以及添加水印

一、我們要做什么

我們要做的是這種效果!
打開一個網頁,百度為例吧


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不支持屏幕旋轉,就可以省去了。

四、Demo如下

https://github.com/ZhaoheMHz/ScrollViewScreenShot

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,833評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,180評論 4 61
  • 1.Notification(通知) 自從Notification被引入之后,蘋果就不斷的更新優化,但這些更新優化...
    MMOTE閱讀 916評論 0 4
  • 開學啦開學啦。看微微特別想玩游戲,但是電腦帶不起來,只能放棄了。真羨慕游戲玩的好的女生啊。這一學期要奮發上進,雖然...
    GoodLee閱讀 354評論 0 0
  • 小寶過敏了,7個月16天的小寶貝因為使用雞蛋白過敏了,孩子滿臉紅彤彤的,耳朵、眼皮、手以及小腳丫都紅腫起來了……孩...
    白敬華閱讀 230評論 0 0