截取带有背景图片的屏幕截图 - iOS

Take a screenshot with background image - iOS

我要截图。在此屏幕截图中,我想要其中的文本和图像。但是,我遇到了一个问题,因为当我截取屏幕截图时,我只看到文字而看不到图像。

我认为问题是 clearContainerView 只包含文本而不包含图像。我不能将图像放在 clearContainerView 内,因为我希望图像拉伸整个屏幕...并且我希望文本居中在标题和标签栏之间(如上图绿色方块所示)。

我的代码和图片如下:

这是我在 Storyboard 中的当前布局:

这就是我想要的截图:

这是我得到的截图:

这是我的代码:

@IBOutlet weak var clearContainerView: UIView!

@IBAction func takeScreenshotTapped(_ sender: UIButton) {
    let screenshot = clearContainerView.screenshot()
    print(screenshot)
}

extension UIView {
    func screenshot() -> UIImage {
        let image = UIGraphicsImageRenderer(size: bounds.size).image { _ in
            drawHierarchy(in: CGRect(origin: .zero, size: bounds.size), afterScreenUpdates: true)
        }

        return image
    }
}

关于如何做到这一点有什么建议吗?

您可以在您的控制器视图上使用以下方法来获取将成为快照视图的 clearContainerView 部分。然后您可以使用该视图对象并截取它的屏幕截图。

resizableSnapshotViewFromRect:afterScreenUpdates:withCapInsets:

您必须传递将成为您的 clearContainerView 框架的矩形。如果您不想要任何可拉伸的内容,您可以传递零插入。它 return 一个视图对象,它将包含您的 imageView 部分 + 您完整的 clearContainerView。然后您可以使用 returned 视图并截屏。

我尝试了以下方法。

我原来的看法。

截图

主要代码:

let frame = containerView.frame
let x: CGFloat = 0
let y = frame.minY.pointsToPixel()
let width = frame.width.pointsToPixel()
let height = frame.height.pointsToPixel()
let rect = CGRect(x: x, y: y, width: width, height: height)
let image = cropImage(image: view.screenshot(), toRect: rect)


extension UIView {
    func screenshot() -> UIImage {
        let image = UIGraphicsImageRenderer(size: bounds.size).image { _ in
            drawHierarchy(in: CGRect(origin: .zero, size: bounds.size), afterScreenUpdates: true)
        }

        return image
    }
}
public extension CGFloat {
    func pointsToPixel() -> CGFloat {
        return self * UIScreen.main.scale
    }

}

输出:

截图后:

我所做的:使用您的方法截取整个视图的屏幕截图,然后通过将 CGPoints 转换为像素来裁剪图像。

您可以使用下面给出的代码截取屏幕截图。它将捕获整个 window 而不是特定视图。但是要注意一件事,如果您不想在屏幕截图中显示 "Title"、"Button" 和 "Tab Bar",那么您需要在 UIGraphicsBeginImageContextWithOptions 之前隐藏它们并显示它们在 UIGraphicsEndImageContext.

之后再次
func takeScreenshot() -> UIImage? {
        var screenshotImage: UIImage?
        let layer = UIApplication.shared.keyWindow!.layer
        let scale = UIScreen.main.scale
        // Hide your title label, button and tab bar here
        UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
        guard let context = UIGraphicsGetCurrentContext() else {return nil}
        layer.render(in:context)
        screenshotImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        // Unhide your title label, button and tab bar here
        return screenshotImage
}

@IBAction func takeScreenshotTapped(_ sender: UIButton) {
    let screenshot = takeScreenshot()
    print(screenshot)
}

一切都很好。我已经为您的预期输出制作了一个演示。

您只需像这样更改您的视图层次结构:

正如你所说的那样,图像在 clearContainerView

之外

代码

class VC: UIViewController {

    @IBOutlet weak var mainVw: UIView!
    @IBOutlet weak var clearContainerView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
    }


    @IBAction func takeImage(_ sender: Any) {

        if let VC_1 = self.storyboard?.instantiateViewController(withIdentifier: "VC1") as? VC1{
            VC_1.img = mainVw.screenshot()
            self.present(VC_1, animated: false, completion: nil)
        }
    }
}

输出:

试试这个! 辅助函数

struct UIGraphicsDrawImageHelper {
    static func drawImage(from image: UIImageView) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(image.bounds.size, image.isOpaque, 0.0)
        image.drawHierarchy(in: image.bounds, afterScreenUpdates: false)
        let renderImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return renderImage
    }
}

调用它

guard let image = UIGraphicsDrawImageHelper.drawImage(from: qrcodeImageView) else { return }

ImageView(Clear Container View)是您想要截屏的视图。您可以将其更改为 uiview 或任何视图。 希望对您有所帮助。

使用这个扩展。

//USAGE



 let image = self.view.snapshot(of:self.<your view>.frame) 

此处 "your view" 应该是层次结构中的基本视图,或者您可以简单地使用

 let image = self.view.snapshot(of:self.view.frame)

扩展

// UIView screenshot
extension UIView {

    /// Create snapshot
    ///
    /// - parameter rect: The `CGRect` of the portion of the view to return. If `nil` (or omitted),
    ///                   return snapshot of the whole view.
    ///
    /// - returns: Returns `UIImage` of the specified portion of the view.

    func snapshot(of rect: CGRect? = nil) -> UIImage? {
        // snapshot entire view

        UIGraphicsBeginImageContextWithOptions(bounds.size,  false, 0.0)
        drawHierarchy(in: bounds, afterScreenUpdates: true)
        let wholeImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        // if no `rect` provided, return image of whole view

        guard let image = wholeImage, let rect = rect else { return wholeImage }

        // otherwise, grab specified `rect` of image

        let scale = image.scale
        let scaledRect = CGRect(x: rect.origin.x * scale, y: rect.origin.y * scale, width: rect.size.width * scale, height: rect.size.height * scale)
        guard let cgImage = image.cgImage?.cropping(to: scaledRect) else { return nil }
        return UIImage(cgImage: cgImage, scale: scale, orientation: .up)
    }

}