iOS_给View的部门区域截图 snapshot for view

打印 上一主题 下一主题

主题 833|帖子 833|积分 2499

1.将整个view截图返回image:

这些 api 已被废弃,所以需要判断 iOS 版本 写两套代码:
Replace usage of UIGraphicsBeginImageContextWithOptions with UIGraphicsImageRenderer.
Replace usage of UIGraphicsGetImageFromCurrentImageContext with UIGraphicsImageRendererContext.currentImage.
Swift 版本:
  1. /// 截图整个view
  2. /// - Returns: image
  3. func mooSnapshot() -> UIImage? {
  4.     if self.window == nil {
  5.         return nil
  6.     }
  7.     let scale = UIScreen.main.scale
  8.     var image: UIImage? = nil
  9.     // 1. 创建绘图渲染格式
  10.     if #available(iOS 10.0, *) {
  11.         let format = UIGraphicsImageRendererFormat()
  12.         format.scale = scale
  13.         format.opaque = false
  14.         // 2. 创建绘图渲染器
  15.         let renderer = UIGraphicsImageRenderer(size: self.bounds.size,
  16.                                                format: format)
  17.         // 3. 绘制图
  18.         image = renderer.image { context in
  19.             let success = self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
  20.             print("draw success: \(success)")
  21.         }
  22.     } else {
  23.         UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, scale);
  24.         let success = self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
  25.         print("draw success: \(success)")
  26.         image = UIGraphicsGetImageFromCurrentImageContext();
  27.         UIGraphicsEndImageContext();
  28.     }
  29.     return image
  30. }
复制代码
OC版本:
  1. - (UIImage * _Nullable)mooSnapshot {
  2.     if (CGRectGetWidth(self.bounds) <= 0.0 || CGRectGetHeight(self.bounds) <= 0.0) {
  3.         return nil;
  4.     }
  5.     if (!self.window) {
  6.         return nil;
  7.     }
  8.     if (!self.superview) {
  9.         return nil;
  10.     }
  11.     CGFloat scale = [UIScreen mainScreen].scale;
  12.     UIImage *image = nil;
  13.     if (@available(iOS 10.0, *)) {
  14.         UIGraphicsImageRendererFormat *format = [[UIGraphicsImageRendererFormat alloc] init];
  15.         format.scale = scale;
  16.         format.opaque = NO;
  17.         UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:self.bounds.size
  18.                                                                                    format:format];
  19.         image = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
  20.             BOOL success = [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
  21.             NSLog(@"%p, Snapshot success: %@", self, @(success));
  22.         }];
  23.     } else {
  24.         UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, scale);
  25.         BOOL success = [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
  26.         NSLog(@"%p,  Snapshot success: %@", self, @(success));
  27.         image = UIGraphicsGetImageFromCurrentImageContext();
  28.         UIGraphicsEndImageContext();
  29.     }
  30.     return image;
  31. }
复制代码

2.截取view的部门区域,返回image:

Capture the frame area of the view.
Swift 版本:
  1. import CoreGraphics
  2. extension UIView {
  3.     /// 截取view的部分区域
  4.     /// - Parameter frame: 需要截取的区域
  5.     /// - Returns: image
  6.     func mooSnapshotForFrame(_ frame: CGRect) -> UIImage? {
  7.         guard let image = self.mooSnapshot() else { return nil }
  8.         guard let cgImage = image.cgImage else { return nil }
  9.         let scale = UIScreen.main.scale
  10.         // 根据屏幕倍率将 frame 进行缩放
  11.         let scaledRect = CGRectApplyAffineTransform(frame,
  12.                                                                                                 CGAffineTransformMakeScale(scale, scale))
  13.         // 根据 缩放frame 进行裁剪
  14.         guard let scaledCGImage = cgImage.cropping(to: scaledRect) else { return nil }
  15.         let returnImage = UIImage(cgImage: scaledCGImage)
  16.         return returnImage
  17.     }
  18. }
复制代码
OC 版本:
  1. - (UIImage * _Nullable)mooSnapshotForFrame:(CGRect)frame {
  2.     if (CGRectGetWidth(frame) <= 0.0 || CGRectGetHeight(frame) <= 0.0) {
  3.         return nil;
  4.     }
  5.     UIImage *image = [self mooSnapshot];
  6.     if (!image) {
  7.         return nil;
  8.     }
  9.     CGFloat scale = [UIScreen mainScreen].scale;
  10.     CGRect scaledRect = CGRectApplyAffineTransform(frame, CGAffineTransformMakeScale(scale, scale));
  11.     CGImageRef cgImage = CGImageCreateWithImageInRect(image.CGImage, scaledRect);
  12.     UIImage *returnImage = [UIImage imageWithCGImage:cgImage];
  13.     CGImageRelease(cgImage);
  14.     return returnImage;
  15. }
复制代码

以下就是将一个view的上半部门截取成image后展示如下:


3.旧方法:

  1. func mooSnapshot() -> UIImage? {
  2.     guard CGRectGetWidth(self.bounds) > 0.0 && CGRectGetHeight(self.bounds) > 0.0 else {
  3.         return nil
  4.     }
  5.     UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, 0.0)
  6.     let success = self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
  7.     print("draw success: \(success)")
  8.     let image = UIGraphicsGetImageFromCurrentImageContext()
  9.     UIGraphicsEndPDFContext()
  10.     return image
  11. }
复制代码
Replace usage of UIGraphicsBeginImageContext with UIGraphicsImageRenderer.
Replace usage of UIGraphicsBeginImageContextWithOptions with UIGraphicsImageRenderer.
Replace usage of UIGraphicsGetImageFromCurrentImageContext with UIGraphicsImageRendererContext.currentImage.
UIGraphicsEndImageContext should only be used alongside UIGraphicsBeginImageContext[WithOptions].
这些旧的 api 已经被废弃了,用文章开头的 api 取代

4.Tips

   Tips1:得在加载到父视图 layout 后触发
Tips2:width 或 height 有一个为空 drawHierarchy 就会 crash(就版iOS不会crash,新版会)
  
参考:

drawViewHierarchyInRect:afterScreenUpdates:
ios drawViewHierarchyInRect crash EXC_BREAKPOINT UNKNOWN

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

自由的羽毛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表