如何在UIView上截取屏幕截图?

139

我想知道我的iPhone应用如何将特定的UIView作为UIImage截屏。

我尝试了这段代码,但我得到的只是一个空白图片。

UIGraphicsBeginImageContext(CGSizeMake(320,480));
CGContextRef context = UIGraphicsGetCurrentContext();
[myUIView.layer drawInContext:context];
UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

myUIView的尺寸为320x480,并且它有一些子视图。 正确的做法是什么?


只需查看 https://dev59.com/QnI95IYBdhLWcg3wsQBm#44517922 - Meet Doshi
16个回答

4
我创建了这个扩展程序,可以从UIView中保存截图。
extension UIView {
func saveImageFromView(path path:String) {
    UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.mainScreen().scale)
    drawViewHierarchyInRect(bounds, afterScreenUpdates: true)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    UIImageJPEGRepresentation(image, 0.4)?.writeToFile(path, atomically: true)

}}

调用:

let pathDocuments = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).first!
let pathImage = "\(pathDocuments)/\(user!.usuarioID.integerValue).jpg"
reportView.saveImageFromView(path: pathImage)

如果您想创建一个png文件,必须进行以下更改:

UIImageJPEGRepresentation(image, 0.4)?.writeToFile(path, atomically: true)

by

UIImagePNGRepresentation(image)?.writeToFile(path, atomically: true)

有什么想法为什么如果我截取UITableViewCell的屏幕截图,我会得到一个空白视图,但如果我截取tableView的屏幕截图,我会得到我期望的内容? - Unome
我尝试了一个例子(UItableViewController),它可以工作,也许你可以把你的代码放在这里进行审查。 - anthonyqz
诀窍在于我需要使用 CGContextTranslateCTM(context, 0, -view.frame.origin.y)。 - Unome

3

Swift 4更新:

extension UIView {
   var screenShot: UIImage?  {
        if #available(iOS 10, *) {
            let renderer = UIGraphicsImageRenderer(bounds: self.bounds)
            return renderer.image { (context) in
                self.layer.render(in: context.cgContext)
            }
        } else {
            UIGraphicsBeginImageContextWithOptions(bounds.size, false, 5);
            if let _ = UIGraphicsGetCurrentContext() {
                drawHierarchy(in: bounds, afterScreenUpdates: true)
                let screenshot = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return screenshot
            }
            return nil
        }
    }
}

2
下面的代码片段用于截屏:
UIGraphicsBeginImageContext(self.muUIView.bounds.size);

[myUIView.layer renderInContext:UIGraphicsGetCurrentContext()];

UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

使用renderInContext:方法代替drawInContext:方法

renderInContext:方法将接收器及其子层渲染到当前上下文中。该方法直接从图层树中进行渲染。


1
-(UIImage *)convertViewToImage
{
    UIGraphicsBeginImageContext(self.bounds.size);
    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

  return image;
}

0

你可以使用以下的UIView类别 -

@implementation UIView (SnapShot)

 - (UIImage *)snapshotImage
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);        
    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO];        
    // old style [self.layer renderInContext:UIGraphicsGetCurrentContext()];        
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();        
    UIGraphicsEndImageContext();        
    return image;
}    
@end

-1
 // MARK: - Actions
 @objc func imageWasSaved(_ image: UIImage, error: Error?, context: UnsafeMutableRawPointer) {
     if let error = error {
         print(error.localizedDescription)
         return
     }

     print("Image was saved in the photo gallery")
     UIApplication.shared.open(URL(string:"photos-redirect://")!)
 }
   
 func takeScreenshot(of view: UIView) {
     
     let bounds = UIScreen.main.bounds
     UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale)

     self.view.drawHierarchy(in: self.view.bounds, afterScreenUpdates: true)

        let screenshot = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
     UIImageWriteToSavedPhotosAlbum(screenshot, self, #selector(imageWasSaved), nil)
 }
   

这个解决方案 - drawHierarchy 已经在以前的答案中被提出了多次。你能否详细阐述一下你的想法,使它能够独立存在? - Cristik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接