不知道各位在開發過程中是否碰到過此類的需求,產品要求開發人員將長長的文章或者是瀏覽的內容進行截屏然后將截圖所獲得的圖片分享出去或者上傳到服務器。
筆者遇到了這樣一個需求,要求開發人員將配置好的商品發送出去的同時截圖上傳至服務器。然后以此作為一個記錄,便于日后方便取用。看了并簡單寫了一個測試demo試了一下。
// 長截圖 類型可以是 tableView或者scrollView 等可以滾動的視圖 根據需要自己改
- (void)saveLongImage:(UITableView *)table {
UIImage* image = nil;
// 下面方法,第一個參數表示區域大小。第二個參數表示是否是非透明的。如果需要顯示半透明效果,需要傳NO,否則傳YES。第三個參數就是屏幕密度了,調整清晰度。
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) {
//保存圖片到相冊
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
}
}
重點是獲取所要截屏的長度和寬度大小。即使獲取屏幕上控件的高度加在一起。獲取將要裁剪的尺寸。那么如果截圖成功了。如何將圖片保存呢?
// 保存后回調方法
- (void)image: (UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
NSString *msg = nil ;
if(error != NULL){
msg = @"保存圖片失敗" ;
}else{
msg = @"保存圖片成功,可到相冊查看" ;
}
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];
}
微信可以檢測到用戶截屏行為(Home + Power),并在稍后點擊附加功能按鈕時詢問用戶是否要發送剛才截屏的圖片,這個用戶體驗非常好。于是乎, 我也想著實現這個功能。
在iOS7之前,?如果用戶截屏,系統會自動取消屏幕上的所有 touch 事件,(使用touchesCancelled:withEvent: 這個方法)那么我們就可以檢測這個方法的調用,然后加載本地最新圖片再加以判斷來實現我們的目的。但在 iOS 7 之后,截屏不再會取消屏幕的 touch 事件,所以導致了 Snapchat 和 Facebook Poke 之類的應用在 iOS 7 剛發布時依賴于系統這個行為的功能受到影響。
如果不采取任何新措施, 我們可以讓應用啟動后在后臺循環檢測相冊內最新一張照片,看它的是否符合截屏的特征。這種方法可行,但這是個笨方法,需要用戶允許你的程序訪問相冊才可以,并且一直在后臺循環會消耗更多的系統資源。
當然, 蘋果封閉了一些東西, 肯定也會給你開放其他東西, 不會讓你走上絕路的。
iOS7提供一個嶄新的推送方法:
UIApplicationUserDidTakeScreenshotNotification
。只要像往常一樣訂閱即可知道什么時候截圖了。
注意:UIApplicationUserDidTakeScreenshotNotification
將會在截圖完成之后顯示
。現在在截圖截取之前無法得到通知。
一。注冊通知:
//注冊通知[[NSNotificationCenter defaultCenter]addObserver:selfselector:@selector(userDidTakeScreenshot:)name:UIApplicationUserDidTakeScreenshotNotificationobject:nil];
二。監聽截屏:
執行操作, 也就是實現上面通知對應的響應函數 ?--?userDidTakeScreenshot
//截屏響應- (void)userDidTakeScreenshot:(NSNotification*)notification{NSLog(@"檢測到截屏");//人為截屏, 模擬用戶截屏行為, 獲取所截圖片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;//添加四個邊陰影imgvPhoto.layer.shadowColor = [UIColorblackColor].CGColor;? ? imgvPhoto.layer.shadowOffset =CGSizeMake(0,0);? ? imgvPhoto.layer.shadowOpacity =0.5;? ? imgvPhoto.layer.shadowRadius =10.0;//添加兩個邊陰影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.打印檢測到截屏
2.獲取截屏圖片。調用[self imageWithScreenshot];這里的imageWithScreenshot是人為截屏, 模擬用戶截屏操作, 獲取截屏圖片。
3.顯示截屏圖片, 以屏幕1/4大小顯示在右下角, 并且加上白色邊框和陰影效果突出顯示。
三。獲取截屏圖片
/**
*? 截取當前屏幕
*
*? @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];}