我想将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)
答案 0 :(得分:100)
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)
}
}
}
Apple不鼓励使用UIGraphicsBeginImageContext
启动iOS 10并引入P3色域。 UIGraphicsBeginImageContext
仅为sRGB且仅为32位。他们引入了全新的UIGraphicsImageRenderer
API,它是完全色彩管理的,基于块的,具有PDF和图像的子类,并自动管理上下文生命周期。查看WWDC16 session 205了解更多详情(图片渲染始于11:50标记左右)
Edit1:为了确保它适用于每台设备,请使用#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!)
}
}
}
答案 1 :(得分:59)
你可以使用扩展名
extension UIImage {
convenience init(view: UIView) {
UIGraphicsBeginImageContext(view.frame.size)
view.layer.render(in:UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.init(cgImage: image!.cgImage!)
}
}
这是swift 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!)
}
}
答案 2 :(得分:40)
通过 drawViewHierarchyInRect:afterScreenUpdates:将您的UIView转换为图像,其比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;
保存已编辑的图像相册
UIImageWriteToSavedPhotosAlbum(snapshotImageFromMyView, nil,nil, nil);
Swift 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
扩展名为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)
答案 3 :(得分:17)
在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)!)
}
}
答案 4 :(得分:16)
UIGraphicsBeginImageContext(self.view.bounds.size);
self.view.layer.renderInContext(UIGraphicsGetCurrentContext())
var screenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
答案 5 :(得分: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();
答案 6 :(得分:13)
,同时仍支持iOS 9及更早版本
"myDatabase": {
"url": "[database url here]",
"connector": "postgresql"}
我不确定这个问题意味着什么:
在应用程序中保存它的最佳方法是什么?(不是相机胶卷)?
答案 7 :(得分: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
}
}
答案 8 :(得分:6)
答案 9 :(得分:5)
var snapshot = overView.snapshotViewAfterScreenUpdates(false)
或在objective-c
UIView* snapshot = [overView snapshotViewAfterScreenUpdates:NO];
答案 10 :(得分:4)
这适用于 Xcode 9 / Swift 3.2 / Swift 4 和 Xcode 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!
}
以下是如何在函数中使用它:
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!
}
}
以下是如何使用函数返回的图像执行某些操作:
@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!
}
我从Paul Hudson那里得到了 Xcode 9 / Swift 3.2 / Swift 4 的答案convert uiview to uiimage
我在很长一段时间之前从某个地方得到了 Xcode 8 / Swift 3 ,我忘记了:(
答案 11 :(得分:4)
您可以使用此扩展程序
轻松使用它// Take a snapshot from a view (just one view)
let viewSnapshot = myView.snapshot
// Take a screenshot (with every views in screen)
let screenSnapshot = UIApplication.shared.snapshot
// Take a snapshot from UIImage initialization
UIImage(view: self.view)
如果您想使用这些扩展方法/变量,请实现此
UIImage扩展程序
extension UIImage {
convenience init(view: UIView) {
if let cgImage = view.snapshot?.cgImage {
self.init(cgImage: cgImage)
} else {
self.init()
}
}
}
UIView扩展
extension UIView {
var snapshot: UIImage? {
UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0.0)
if UIGraphicsGetCurrentContext() != nil {
drawHierarchy(in: bounds, afterScreenUpdates: true)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return screenshot
}
return nil
}
}
UIApplication extension
extension UIApplication {
var snapshot: UIImage? {
return keyWindow?.rootViewController?.view.snapshot
}
}
答案 12 :(得分:2)
或iOS 10+你可以使用新的UIGraphicsImageRenderer +推荐的drawHierarchy,在某些情况下可以比layer.renderInContext快得多
extension UIView {
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(size: self.bounds.size)
return renderer.image { _ in
self.drawHierarchy(in: CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height), afterScreenUpdates: false)
}
}
}
答案 13 :(得分:1)
Swift 3 :
中的实施在课堂范围之外添加以下代码。
if(a[4] == '\0')
用法:
extension UIImage {
convenience init(_ view: UIView) {
UIGraphicsBeginImageContext(view.frame.size)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.init(cgImage: (image?.cgImage)!)
}
}
答案 14 :(得分:1)
谢谢@Bao Tuan Diep!我想补充一点。
使用代码时:
yourView.layer.render(in:UIGraphicsGetCurrentContext()!)
您必须注意:
- If you had used `autoLayout` or `Masonry` in `yourView` (that you want to convert) .
- If you did not add `yourView` to another view which means that `yourView` was not used as a subview but just an object.
然后,您必须使用:
[yourView setNeedsLayout];
[yourView layoutIfNeeded];
在yourView
之前更新yourView.layer.render(in:UIGraphicsGetCurrentContext()!)
。
否则您可能会得到一个不包含元素的图像对象
答案 15 :(得分:1)
Swift 4.2
import Foundation
import UIKit
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)!)
}
}
使用:
let img = UIImage.init(view:self.holderView)
答案 16 :(得分:0)
自iOS 10起,带有新UIGraphicsImageRenderer的Initializer:
extension UIImage{
convenience init(view: UIView) {
let renderer = UIGraphicsImageRenderer(size: self.bounds.size)
let canvas = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height)
let image = renderer.image { _ in
self.drawHierarchy(in: canvas, afterScreenUpdates: false)
}
self.init(cgImage: (image?.cgImage)!)
}
}
答案 17 :(得分:0)
和我一起工作很好!
Swift4
extension UIView {
func toImage() -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
self.drawHierarchy(in: self.bounds, afterScreenUpdates: false)
let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return snapshotImageFromMyView!
}
}
答案 18 :(得分:0)
我实施了@Naveed J.这样的方法,它就像一个魅力。
这是他的扩展:
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) } } }
以下是我实施它的方式。
//create an image from yourView to display
//determine the frame of the view/imageimage
let screen = self.superview!.bounds
let width = screen.width / 4 //make image 1/4 width of screen
let height = width
let frame = CGRect(x: 0, y: 0, width: width, height: height)
let x = (screen.size.width - frame.size.width) * 0.5
let y = (screen.size.height - frame.size.height) * 0.5
let mainFrame = CGRect(x: x, y: y, width: frame.size.width, height: frame.size.height)
let yourView = YourView() //instantiate yourView
yourView.frame = mainFrame //give it the frame
yourView.setNeedsDisplay() //tell it to display (I am not 100% sure this is needed)
let characterViewImage = yourView.asImage()
答案 19 :(得分:0)
对于包含模糊子视图的视图(例如 UIVisualEffectView 实例),仅 drawViewHierarchyInRect:afterScreenUpdates 有效。
@ViJay Avhad's answer对于这种情况是正确的。
答案 20 :(得分:0)
当视图包含Scene Kit子视图,Metal或Sprite Kit的子视图时,无法使用UIGraphicsImageRenderer。在这种情况下,请使用
let renderer = UIGraphicsImageRenderer(size: view.bounds.size)
let image = renderer.image { ctx in
view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
}
答案 21 :(得分:-1)
wordpress_logged_in_something