不知道各位在開(kāi)發(fā)過(guò)程中是否碰到過(guò)此類(lèi)的需求,產(chǎn)品要求開(kāi)發(fā)人員將長(zhǎng)長(zhǎng)的文章或者是瀏覽的內(nèi)容進(jìn)行截屏然后將截圖所獲得的圖片分享出去或者上傳到服務(wù)器。
筆者遇到了這樣一個(gè)需求,要求開(kāi)發(fā)人員將配置好的商品發(fā)送出去的同時(shí)截圖上傳至服務(wù)器。然后以此作為一個(gè)記錄,便于日后方便取用??戳瞬⒑?jiǎn)單寫(xiě)了一個(gè)測(cè)試demo試了一下。
// 長(zhǎng)截圖 類(lèi)型可以是 tableView或者scrollView 等可以滾動(dòng)的視圖 根據(jù)需要自己改
- (void)saveLongImage:(UITableView *)table {
UIImage* image = nil;
// 下面方法,第一個(gè)參數(shù)表示區(qū)域大小。第二個(gè)參數(shù)表示是否是非透明的。如果需要顯示半透明效果,需要傳NO,否則傳YES。第三個(gè)參數(shù)就是屏幕密度了,調(diào)整清晰度。
UIGraphicsBeginImageContextWithOptions(table.contentSize, YES, [UIScreen mainScreen].scale);
CGPoint savedContentOffset = table.contentOffset;
CGRect savedFrame = table.frame;
table.contentOffset = CGPointZero;
table.frame = CGRectMake(0, 0, table.contentSize.width, table.contentSize.height);
[table.layer renderInContext: UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
table.contentOffset = savedContentOffset;
table.frame = savedFrame;
UIGraphicsEndImageContext();
if (image != nil) {
//保存圖片到相冊(cè)
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
}
}
重點(diǎn)是獲取所要截屏的長(zhǎng)度和寬度大小。即使獲取屏幕上控件的高度加在一起。獲取將要裁剪的尺寸。那么如果截圖成功了。如何將圖片保存呢?
// 保存后回調(diào)方法
- (void)image: (UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
NSString *msg = nil ;
if(error != NULL){
msg = @"保存圖片失敗" ;
}else{
msg = @"保存圖片成功,可到相冊(cè)查看" ;
}
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:@"確定" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:cancelAction];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
}
微信可以檢測(cè)到用戶(hù)截屏行為(Home + Power),并在稍后點(diǎn)擊附加功能按鈕時(shí)詢(xún)問(wèn)用戶(hù)是否要發(fā)送剛才截屏的圖片,這個(gè)用戶(hù)體驗(yàn)非常好。于是乎, 我也想著實(shí)現(xiàn)這個(gè)功能。
在iOS7之前,?如果用戶(hù)截屏,系統(tǒng)會(huì)自動(dòng)取消屏幕上的所有 touch 事件,(使用touchesCancelled:withEvent: 這個(gè)方法)那么我們就可以檢測(cè)這個(gè)方法的調(diào)用,然后加載本地最新圖片再加以判斷來(lái)實(shí)現(xiàn)我們的目的。但在 iOS 7 之后,截屏不再會(huì)取消屏幕的 touch 事件,所以導(dǎo)致了 Snapchat 和 Facebook Poke 之類(lèi)的應(yīng)用在 iOS 7 剛發(fā)布時(shí)依賴(lài)于系統(tǒng)這個(gè)行為的功能受到影響。
如果不采取任何新措施, 我們可以讓?xiě)?yīng)用啟動(dòng)后在后臺(tái)循環(huán)檢測(cè)相冊(cè)內(nèi)最新一張照片,看它的是否符合截屏的特征。這種方法可行,但這是個(gè)笨方法,需要用戶(hù)允許你的程序訪問(wèn)相冊(cè)才可以,并且一直在后臺(tái)循環(huán)會(huì)消耗更多的系統(tǒng)資源。
當(dāng)然, 蘋(píng)果封閉了一些東西, 肯定也會(huì)給你開(kāi)放其他東西, 不會(huì)讓你走上絕路的。
iOS7提供一個(gè)嶄新的推送方法:
UIApplicationUserDidTakeScreenshotNotification
。只要像往常一樣訂閱即可知道什么時(shí)候截圖了。
注意:UIApplicationUserDidTakeScreenshotNotification
將會(huì)在截圖完成之后顯示
?,F(xiàn)在在截圖截取之前無(wú)法得到通知。
一。注冊(cè)通知:
//注冊(cè)通知[[NSNotificationCenter defaultCenter]addObserver:selfselector:@selector(userDidTakeScreenshot:)name:UIApplicationUserDidTakeScreenshotNotificationobject:nil];
二。監(jiān)聽(tīng)截屏:
執(zhí)行操作, 也就是實(shí)現(xiàn)上面通知對(duì)應(yīng)的響應(yīng)函數(shù) ?--?userDidTakeScreenshot
//截屏響應(yīng)- (void)userDidTakeScreenshot:(NSNotification*)notification{NSLog(@"檢測(cè)到截屏");//人為截屏, 模擬用戶(hù)截屏行為, 獲取所截圖片UIImage*image_ = [selfimageWithScreenshot];//添加顯示UIImageView*imgvPhoto = [[UIImageViewalloc]initWithImage:image_];? ? imgvPhoto.frame =CGRectMake(self.window.frame.size.width/2,self.window.frame.size.height/2,self.window.frame.size.width/2,self.window.frame.size.height/2);//添加邊框CALayer* layer = [imgvPhoto layer];? ? layer.borderColor = [? ? [UIColorwhiteColor]CGColor];? ? layer.borderWidth =5.0f;//添加四個(gè)邊陰影imgvPhoto.layer.shadowColor = [UIColorblackColor].CGColor;? ? imgvPhoto.layer.shadowOffset =CGSizeMake(0,0);? ? imgvPhoto.layer.shadowOpacity =0.5;? ? imgvPhoto.layer.shadowRadius =10.0;//添加兩個(gè)邊陰影imgvPhoto.layer.shadowColor = [UIColorblackColor].CGColor;? ? imgvPhoto.layer.shadowOffset =CGSizeMake(4,4);? ? imgvPhoto.layer.shadowOpacity =0.5;? ? imgvPhoto.layer.shadowRadius =2.0;? ? [self.window addSubview:imgvPhoto];}
我這里的?userDidTakeScreenshot 總共做了3件事
1.打印檢測(cè)到截屏
2.獲取截屏圖片。調(diào)用[self imageWithScreenshot];這里的imageWithScreenshot是人為截屏, 模擬用戶(hù)截屏操作, 獲取截屏圖片。
3.顯示截屏圖片, 以屏幕1/4大小顯示在右下角, 并且加上白色邊框和陰影效果突出顯示。
三。獲取截屏圖片
/**
*? 截取當(dāng)前屏幕
*
*? @return NSData *
*/- (NSData*)dataWithScreenshotInPNGFormat{CGSizeimageSize =CGSizeZero;UIInterfaceOrientationorientation = [UIApplicationsharedApplication].statusBarOrientation;if(UIInterfaceOrientationIsPortrait(orientation))imageSize = [UIScreenmainScreen].bounds.size;elseimageSize =CGSizeMake([UIScreenmainScreen].bounds.size.height, [UIScreenmainScreen].bounds.size.width);UIGraphicsBeginImageContextWithOptions(imageSize,NO,0);CGContextRefcontext =UIGraphicsGetCurrentContext();for(UIWindow*windowin[[UIApplicationsharedApplication] 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);}elseif(orientation ==UIInterfaceOrientationLandscapeRight){CGContextRotateCTM(context, -M_PI_2);CGContextTranslateCTM(context, -imageSize.height,0);}elseif(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();returnUIImagePNGRepresentation(image);}/**
*? 返回截取到的圖片
*
*? @return UIImage *
*/- (UIImage*)imageWithScreenshot{NSData*imageData = [selfdataWithScreenshotInPNGFormat];return[UIImageimageWithData:imageData];}