ios - 快速捕获自由形式的视图控制器屏幕截图
问题描述
我想捕获整个可滚动视图控制器的屏幕截图。其高度为 1025 的自由形式视图控制器。屏幕截图图像应为 1045 或滚动视图框架的整个屏幕。
我试过这段代码,但它只捕获可见的矩形。我想要滚动视图下的整个视图的屏幕截图
fileprivate extension UIScrollView {
func screenshot() -> UIImage? {
// begin image context
UIGraphicsBeginImageContextWithOptions(contentSize, false, 0.0)
// save the orginal offset & frame
let savedContentOffset = contentOffset
let savedFrame = frame
// end ctx, restore offset & frame before returning
defer {
UIGraphicsEndImageContext()
contentOffset = savedContentOffset
frame = savedFrame
}
// change the offset & frame so as to include all content
contentOffset = .zero
frame = CGRect(x: 0, y: 0, width: contentSize.width, height: contentSize.height)
guard let ctx = UIGraphicsGetCurrentContext() else {
return nil
}
layer.render(in: ctx)
let image = UIGraphicsGetImageFromCurrentImageContext()
return image
}
}
解决方案
您的代码中的问题是layer.render
触发 layoutSubviews 并重置您的框架。
由于我们不想放松所有约束,我们需要存储它们,在截屏时禁用,然后再次打开它们:
extension UIScrollView {
func screenshot() -> UIImage? {
UIGraphicsBeginImageContextWithOptions(contentSize, false, 0.0)
// save the orginal offset, take a ref to all constraints related to the view
let savedContentOffset = contentOffset
let actualConstraints = relatedConstraints()
// deactivate non needed constraints so they won't stop us from resiging scroll view
NSLayoutConstraint.deactivate(actualConstraints)
// enable auth generated constraints based on the frame
translatesAutoresizingMaskIntoConstraints = true
frame = CGRect(x: 0, y: 0, width: contentSize.width, height: contentSize.height)
contentOffset = .zero
defer {
UIGraphicsEndImageContext()
// reset original constraints
translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(actualConstraints)
// layout superview needed before resetting content offset
superview?.layoutIfNeeded()
contentOffset = savedContentOffset
}
guard let ctx = UIGraphicsGetCurrentContext() else {
return nil
}
layer.render(in: ctx)
let image = UIGraphicsGetImageFromCurrentImageContext()
return image
}
}
extension UIView {
func relatedConstraints() -> [NSLayoutConstraint] {
var constraints = self.constraints
var parent = superview
while parent != nil {
constraints.append(contentsOf: parent!.constraints.filter { $0.firstItem === self || $0.secondItem === self })
parent = parent!.superview
}
return constraints
}
}
推荐阅读
- google-bigquery - 如何将日期数据类型从字符串更改为日期
- c++ - OpenGL透明纹理重叠/混合问题
- python - 为什么多类逻辑回归模型系数会根据类标签而变化?
- c++ - 如何在保持连续性的同时拆分 OpenCV 矩阵?
- windows - 无法在 GoLand 中使用已安装的软件包
- c - C exec 多命令
- javascript - React-MDL 网格单元显示在 http://localhost:3000/ 和托管网站的不同位置
- powershell - Powershell 绑定参数路径
- c# - 使用 selenium chromedriver 上传文件
- html - 如何一次将一个选项从一个选择克隆到另一个?