截取带有背景图片的屏幕截图 - 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)
}
}
我要截图。在此屏幕截图中,我想要其中的文本和图像。但是,我遇到了一个问题,因为当我截取屏幕截图时,我只看到文字而看不到图像。
我认为问题是 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)
}
}