I have a UIView named overView:
overView.frame = CGRectMake(self.view.frame.width/25, self.view.frame.height/25, self.view.frame.width/1.3, self.view.frame.height/1.2)
I want to take a screenshot of this view only and not my entire screen. And make the screenshot of size:
(CGSizeMake(2480,3508 )
Here is my code:
UIGraphicsBeginImageContextWithOptions(CGSizeMake(2480,3508 ), false, 0);
self.view.drawViewHierarchyInRect(CGRectMake(-self.view.frame.width/25, -self.view.frame.height/25,2480,3508), afterScreenUpdates: true)
var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext()
The screenshot is of the required size however it takes the screenshot of the entire view instead of just "overView".
For drawing of one view, just use this:
// Begin context
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.mainScreen().scale)
// Draw view in that context
drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
// And finally, get image
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
If you want to use it multiple times, probably extension would do the job:
//Swift4
extension UIView {
func takeScreenshot() -> UIImage {
// Begin context
UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale)
// Draw view in that context
drawHierarchy(in: self.bounds, afterScreenUpdates: true)
// And finally, get image
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
if (image != nil)
{
return image!
}
return UIImage()
}
}
//Old Swift
extension UIView {
func takeScreenshot() -> UIImage {
// Begin context
UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.mainScreen().scale)
// Draw view in that context
drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true)
// And finally, get image
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
To explain what those parameters do:
UIGraphicsBeginImageContextWithOptions() creates a temporary rendering
context into which the original is drawn. The first argument, size, is
the target size of the scaled image. The second argument, isOpaque is
used to determine whether an alpha channel is rendered. Setting this
to false for images without transparency (i.e. an alpha channel) may
result in an image with a pink hue. The third argument scale is the
display scale factor. When set to 0.0, the scale factor of the main
screen is used, which for Retina displays is 2.0 or higher (3.0 on the
iPhone 6 Plus).
More about it here http://nshipster.com/image-resizing/
As for the draw call, Apple Docs explains it to detail here and here
swift 4 and iOS 10+
extension UIView {
func screenshot() -> UIImage {
return UIGraphicsImageRenderer(size: bounds.size).image { _ in
drawHierarchy(in: CGRect(origin: .zero, size: bounds.size), afterScreenUpdates: true)
}
}
}
For Taking Screen Short Use This Solution. Hear I can Done How to Take Screen Short UIView with UIImage..
let img = self.captureScreen() // CaptureScreen Is A Function
let someNSDate = NSDate()
let myTimeStamp = someNSDate.timeIntervalSince1970
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
if let data = UIImageJPEGRepresentation(img, 0.8)
{
let filename = documentsDirectory.appendingPathComponent("Img_\(myTimeStamp).jpeg")
SavedImage_Ary.insert("Img_\(myTimeStamp).jpeg", at: 0) // SavedImage Is A NSMutableArray Where You Can Store your Image
//print(SavedImage_Ary)
try? data.write(to: filename)
UserDefaults.standard.setValue(SavedImage_Ary, forKey: "Saved_Image")
Save_Img = true
// self.dismiss(animated: true, completion: nil)
Select_Flag = "textdata"
let vc = self.storyboard?.instantiateViewController(withIdentifier: "photovc") as! UINavigationController
self.present(vc, animated: true, completion: nil)
}
// MARK : Function
func captureScreen() -> UIImage
{
UIGraphicsBeginImageContextWithOptions(Capture_View.frame.size, false, 0);
Capture_View.drawHierarchy(in: Capture_View.bounds, afterScreenUpdates: true)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
Swift 4.x and iOS 10+ with fallback solution:
extension UIView {
func screenshot() -> UIImage {
if #available(iOS 10.0, *) {
return UIGraphicsImageRenderer(size: bounds.size).image { _ in
drawHierarchy(in: CGRect(origin: .zero, size: bounds.size), afterScreenUpdates: true)
}
} else {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale)
drawHierarchy(in: self.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
UIGraphicsEndImageContext()
return image
}
}
}
An alternative for Alessandro's answer, a bit more brief and Swift style:
extension UIView {
var snapshot: UIImage {
return UIGraphicsImageRenderer(size: bounds.size).image { _ in
drawHierarchy(in: bounds, afterScreenUpdates: true)
}
}
}
func screenShotMethod()->UIImage
{
let layer = self.view.layer
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
layer.render(in: UIGraphicsGetCurrentContext()!)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return screenshot!
}