我們在開發(fā)中經常需要使用截屏功能或者把某個view生成一張圖片的功能,還有可能需要拼接在一起組成一張大圖,另外有可能給一張大圖添加水印圖等。
屏幕截圖
屏幕截圖和view截成圖一樣,只是把對應的view換成window就行,示例代碼如下
UIGraphicsBeginImageContextWithOptions([UIApplication sharedApplication].keyWindow.bounds.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIApplication sharedApplication].keyWindow .layer renderInContext:context];
UIImage *image= UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
這樣截圖出來的圖片沒有頂部狀態(tài)欄,因為狀態(tài)欄并不在keyWindow對應的view上,所以我們要加上相應的UIStatueBar
UIGraphicsBeginImageContextWithOptions([UIApplication sharedApplication].keyWindow.bounds.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIApplication sharedApplication].keyWindow .layer renderInContext:context];
//添加頂部狀態(tài)欄
UIView *statusBarView = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
[statusBarView.layer renderInContext:context];
UIImage *image= UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
獲取頂部狀態(tài)欄View的方法OTScreenshotHelper中用的是runtime,也是可以獲取到,有興趣的同學可以去看下https://github.com/OpenFibers/OTScreenshotHelper
以上方法還有一個問題,就是對于有UIPickerView在頁面上,PickView會有黑邊,所以我們要把renderInContext替換成drawViewHierarchyInRect,示例代碼如下
UIGraphicsBeginImageContextWithOptions([UIApplication sharedApplication].keyWindow.bounds.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIApplication sharedApplication].keyWindow drawViewHierarchyInRect:(CGRect){.origin=CGPointZero, .size=[UIApplication sharedApplication].keyWindow.bounds.size} afterScreenUpdates:YES];
//添加頂部狀態(tài)欄
UIView *statusBarView = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
[statusBarView.layer renderInContext:context];
UIImage *image= UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIScrollView圖片裁剪
一般的view的生成圖片和上面截屏方法類似,而且可以不考慮頂部狀態(tài)欄。對于UIScrollView用上面的方法獲取的圖片也是我們可見的,如果我們想要獲取整個ContentSize的圖片,對于UITableView和UICollectionView往往會留下一片空白部分,達不到我們想要的效果。要達到整個都截取的話,我們可以分段截圖,然后拼接,也可以改變其frame,讓所有cell都渲染出來。
- (UIImage *)screenshotImageWithScrollView:(UIScrollView *)scrollView
imageSize:(CGSize)size{
CGPoint orignalContentOffset = scrollView.contentOffset;
CGRect orignalFrame = scrollView.frame;
UIScrollView *rt = scrollView;
CGRect frm = scrollView.frame;
frm.size.height = size.height;
rt.frame = frm;
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
[rt.layer renderInContext:context];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
scrollView.contentOffset = orignalContentOffset;
scrollView.frame = orignalFrame;
return viewImage;
}
上面就是改變ScrollView的frame,高度和contentSize的height一樣,等截圖才做完成后重新回到它原狀態(tài)。裁剪ScrollView生成圖片的尺寸和我們給的尺寸有變差,需要注意生成圖片的scale,裁剪示例代碼如下
UIImage *screenImg = [self screenshotImageWithScrollView:scrollView imageSize:scrollView.contentSize];
CGImageRef screenImageRef = screenImg.CGImage;
CGImageRef rectImageRef = CGImageCreateWithImageInRect(screenImageRef, CGRectMake(rect.origin.x*screenImg.scale, rect.origin.y*screenImg.scale, rect.size.width*screenImg.scale, rect.size.height*screenImg.scale));
UIImage* rectImage = [UIImage imageWithCGImage:rectImageRef];
CGImageRelease(rectImageRef);
圖片添加水印
圖片拼接、添加水印都基本一樣,都在畫布中畫出圖片
- (UIImage *)imageAddMaskWithImage:(UIImage *)orignalImage
imageSize:(CGSize)imageSize
maskImage:(UIImage *)maskImage
maskImageRect:(CGRect)maskRect
maskAlpha:(CGFloat)maskAlpha{
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
[orignalImage drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)];
[maskImage drawInRect:maskRect blendMode:kCGBlendModeNormal alpha:maskAlpha];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
}
總結
以上都是靜態(tài)頁面的截圖,對于正在執(zhí)行動畫的頁面沒測試,有興趣的同學可以嘗試一下。另外對于WebView上述方式是截取不了整個WebView,這有個解決方法http://www.itdecent.cn/p/ef50defb979d,最后附上demoOC、Swift。