如何将UIView转换为图像

Sam*_*ain 68 screenshot uiview ios swift

我想将UIView转换为图像并将其保存在我的应用程序中.有人可以请告诉我如何截取视图的截图或将其转换为图像,以及将其保存在应用程序(不是相机胶卷)的最佳方法是什么?以下是视图的代码:

var overView   = UIView(frame: CGRectMake(0, 0, self.view.frame.width/1.3, self.view.frame.height/1.3))
overView.center = CGPointMake(CGRectGetMidX(self.view.bounds),
CGRectGetMidY(self.view.bounds)-self.view.frame.height/16);
overView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(overView)
self.view.bringSubviewToFront(overView)
Run Code Online (Sandbox Code Playgroud)

Nav*_* J. 129

扩展UIView应该做的伎俩.

extension UIView {

    // Using a function since `var image` might conflict with an existing variable
    // (like on `UIImageView`)
    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Apple不鼓励使用UIGraphicsBeginImageContext启动iOS 10并引入P3色域.UIGraphicsBeginImageContext是sRGB和32位.他们推出了全新的UIGraphicsImageRendererAPI,它是完全色彩管理的,基于块的,具有PDF和图像的子类,并自动管理上下文生命周期.查看WWDC16会话205了解更多详情(图像渲染始于11:50标记左右)

编辑1:为了确保它适用于每个设备,使用#available回退到早期版本的iOS:

extension UIView {

    // Using a function since `var image` might conflict with an existing variable
    // (like on `UIImageView`)
    func asImage() -> UIImage {
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        } else {
            UIGraphicsBeginImageContext(self.frame.size)
            self.layer.render(in:UIGraphicsGetCurrentContext()!)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return UIImage(cgImage: image!.cgImage!)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该标记为正确的答案.所有其他选项将导致渲染图像失去清晰度并看起来像素化/模糊. (8认同)
  • 唯一正确的方法!初学者的用法是: let image = customView.asImage() (2认同)
  • 是否可以将 UIView 渲染为透明背景?我的有一些圆角。 (2认同)
  • 谢谢!如果有人知道,我很想知道 https://www.hackingwithswift.com/example-code/media/how-to-render-a-uiview-to-a-uiimage 中的代码有什么区别: return renderer.image { ctx in drawHierarchy(in: bounds, afterScreenUpdates: true) } (2认同)

Bao*_*iep 61

你可以使用扩展名

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in:UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: image!.cgImage!)
    }
}
Run Code Online (Sandbox Code Playgroud)

这里是迅捷的3/4版本:

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in:UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: image!.cgImage!)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `让image = UIImage(view:myView)` (6认同)
  • 我很尴尬是这个问这个,但我怎么称呼这个?我没有图像和UIView,我想成为一个图像.上面的代码给了我一个UIImage扩展......但现在是什么? (4认同)
  • 对我来说不起作用,因为 UIGraphicsGetCurrentContext() 可能为零并且代码崩溃。 (2认同)
  • 您还应该记住屏幕的缩放比例,因此我将用以下内容替换初始化程序的第一行:UIGraphicsBeginImageContextWithOptions(view.frame.size,false,UIScreen.main.scale)。 (2认同)

ViJ*_*had 41

通过将您的UIView图像drawViewHierarchyInRect:afterScreenUpdates:这是不是renderInContext快很多倍

重要说明:不要从viewDidLoad或viewWillAppear调用此函数,请确保在视图显示/加载后完全捕获视图

对象C.

     UIGraphicsBeginImageContextWithOptions(myView.bounds.size, myView.opaque, 0.0f);
     [myView drawViewHierarchyInRect:myView.bounds afterScreenUpdates:NO];
     UIImage *snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();

     myImageView.image =  snapshotImageFromMyView;
Run Code Online (Sandbox Code Playgroud)

保存编辑过的图像相册

     UIImageWriteToSavedPhotosAlbum(snapshotImageFromMyView, nil,nil, nil);
Run Code Online (Sandbox Code Playgroud)

斯威夫特3/4

    UIGraphicsBeginImageContextWithOptions(myView.bounds.size, myView.isOpaque, 0.0)
    myView.drawHierarchy(in: myView.bounds, afterScreenUpdates: false)
    let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    print(snapshotImageFromMyView)
    myImageView.image = snapshotImageFromMyView
Run Code Online (Sandbox Code Playgroud)

超级简单的扩展,扩展,iOS11,swift3/4

extension UIImage{
    convenience init(view: UIView) {

    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
    view.drawHierarchy(in: view.bounds, afterScreenUpdates: false)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    self.init(cgImage: (image?.cgImage)!)

  }
}


Use : 
 //myView is completly loaded/visible , calling this code after only after viewDidAppear is call
 imgVV.image = UIImage.init(view: myView)
 // Simple image object
 let img =  UIImage.init(view: myView)
Run Code Online (Sandbox Code Playgroud)

  • 没有为我工作我为我的UiImage得到了一个黑屏 (3认同)

小智 18

在iOS 10上:

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in: UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: (image?.cgImage)!)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这会导致崩溃。 (3认同)

Vak*_*kas 16

    UIGraphicsBeginImageContext(self.view.bounds.size);        
    self.view.layer.renderInContext(UIGraphicsGetCurrentContext())
    var screenShot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
Run Code Online (Sandbox Code Playgroud)

  • 截图图片质量不高,我该怎么办? (6认同)

Jon*_*lis 14

从iOS 10和Swift 3开始的最佳实践

同时仍然支持iOS 9及更早版本

extension UIView {

    func asImage() -> UIImage? {
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        } else {
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
            defer { UIGraphicsEndImageContext() }
            guard let currentContext = UIGraphicsGetCurrentContext() else {
                return nil
            }
            self.layer.render(in: currentContext)
            return UIGraphicsGetImageFromCurrentImageContext()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我不确定这个问题意味着什么:

什么是在应用程序中保存它的最佳方法(非相机胶卷)?


Sam*_*ain 13

例如,如果我有一个大小的视图:50 50 100,100.我可以使用以下方法截取屏幕截图:

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), false, 0);
    self.view.drawViewHierarchyInRect(CGRectMake(-50,-5-,view.bounds.size.width,view.bounds.size.height), afterScreenUpdates: true)
    var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
Run Code Online (Sandbox Code Playgroud)


Tin*_*ino 7

在我看来,初始化的方法不是很好,因为它创建了两个图像.

我更喜欢这个:

extension UIView {
    var snapshot: UIImage? {
        UIGraphicsBeginImageContext(self.frame.size)
        guard let context = UIGraphicsGetCurrentContext() else {
            return nil
        }
        layer.render(in: context)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}
Run Code Online (Sandbox Code Playgroud)


Den*_*Den 6

Swift 4.2,iOS 10

extension UIView {

    // If Swift version is lower than 4.2, 
    // You should change the name. (ex. var renderedImage: UIImage?)

    var image: UIImage? {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in layer.render(in: rendererContext.cgContext) }
    }
}
Run Code Online (Sandbox Code Playgroud)

样品

let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = .blue

let view2 = UIView(frame: CGRect(x: 10, y: 10, width: 20, height: 20))
view2.backgroundColor = .red
view.addSubview(view2)

let imageView = UIImageView(image: view.image)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Yed*_*iss 5

var snapshot = overView.snapshotViewAfterScreenUpdates(false)
Run Code Online (Sandbox Code Playgroud)

或者在目标c中

UIView* snapshot = [overView snapshotViewAfterScreenUpdates:NO];
Run Code Online (Sandbox Code Playgroud)


Lan*_*ria 5

这对我来说适用于Xcode 9 / Swift 3.2 / Swift 4Xcode 8 / Swift 3

 if #available(iOS 10.0, *) {

     // for Xcode 9/Swift 3.2/Swift 4 -Paul Hudson's code
     let renderer = UIGraphicsImageRenderer(size: view!.bounds.size)
     let capturedImage = renderer.image { 
         (ctx) in
         view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: true)
     }
     return capturedImage

 } else {

     // for Xcode 8/Swift 3
     UIGraphicsBeginImageContextWithOptions((view!.bounds.size), view!.isOpaque, 0.0)
     view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: false)
     let capturedImage = UIGraphicsGetImageFromCurrentImageContext()
     UIGraphicsEndImageContext()
     return capturedImage!
 }
Run Code Online (Sandbox Code Playgroud)

这是在函数内使用它的方法:

fileprivate func captureUIImageFromUIView(_ view:UIView?) -> UIImage {

     guard (view != nil) else{

        // if the view is nil (it's happened to me) return an alternative image
        let errorImage = UIImage(named: "Error Image")
        return errorImage
     }

     // if the view is all good then convert the image inside the view to a uiimage
     if #available(iOS 10.0, *) {

         let renderer = UIGraphicsImageRenderer(size: view!.bounds.size)
         let capturedImage = renderer.image { 
             (ctx) in
             view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: true)
         }
         return capturedImage

     } else {

         UIGraphicsBeginImageContextWithOptions((view!.bounds.size), view!.isOpaque, 0.0)
         view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: false)
         let capturedImage = UIGraphicsGetImageFromCurrentImageContext()
         UIGraphicsEndImageContext()
         return capturedImage!
     }
}
Run Code Online (Sandbox Code Playgroud)

这是处理从函数返回的图像的方法:

@IBOutlet weak fileprivate var myCustomView: UIView!
var myPic: UIImage?

let myImageView = UIImageView()

@IBAction fileprivate func saveImageButtonTapped(_ sender: UIButton) {

   myPic = captureUIImageFromUIView(myCustomView)

   // display the pic inside a UIImageView
   myImageView.image = myPic!
}
Run Code Online (Sandbox Code Playgroud)

我从Paul Hudson 得到了Xcode 9 / Swift 3.2 / Swift 4的答案将uiview转换为uiimage

很久以前我从某处获得Xcode 8 / Swift 3,却忘了:(