Tim*_*van 55 iphone core-graphics ipad ios
我有一个UIScrollView实现takeScreenshot方法的decedent,如下所示:
-(void)takeScreenshot {
CGRect contextRect = CGRectMake(0, 0, 768, 1004);
UIGraphicsBeginImageContext(contextRect.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// do something with the viewImage here.
}
Run Code Online (Sandbox Code Playgroud)
这基本上移动到滚动视图的顶部,并截取可见区域的屏幕截图.当iPad面向人像时,它可以正常工作,但当它处于横向时,图像的底部会被切断(因为可见区域的高度仅为748,而不是1004).
是否有可能获得快照UIScrollView,包括不在屏幕上的区域?或者我需要向下滚动视图,拍摄第二张照片并将它们拼接在一起?
Ste*_*ntz 110
这是有效的代码......
- (IBAction) renderScrollViewToImage
{
UIImage* image = nil;
UIGraphicsBeginImageContext(_scrollView.contentSize);
{
CGPoint savedContentOffset = _scrollView.contentOffset;
CGRect savedFrame = _scrollView.frame;
_scrollView.contentOffset = CGPointZero;
_scrollView.frame = CGRectMake(0, 0, _scrollView.contentSize.width, _scrollView.contentSize.height);
[_scrollView.layer renderInContext: UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
_scrollView.contentOffset = savedContentOffset;
_scrollView.frame = savedFrame;
}
UIGraphicsEndImageContext();
if (image != nil) {
[UIImagePNGRepresentation(image) writeToFile: @"/tmp/test.png" atomically: YES];
system("open /tmp/test.png");
}
}
Run Code Online (Sandbox Code Playgroud)
最后几行只是将图像写入/tmp/test.png,然后在Preview.app中打开它.这显然只适用于模拟器:-)
ScrollViewScreenShot Github存储库中的完整项目
小智 21
对我来说回答/sf/answers/247796111/没有用.我有一个在iOS 8上实现这个的任务.
实际上这种方法适用于iPhone,但iPad(simu和真实设备)是另一种情况.它只是呈现可见部分,其余图像只是空白.
我试过drawViewHierarchyInRect- 没有运气.取决于afterScreenUpdates存在true或false我拉伸图像的一部分或再次只是图像的一部分.
因此,我发现实现正确屏幕截图的唯一方法是将scrollview添加到另一个临时视图并进行渲染.
示例代码如下(我的VC中的scrollview是插座)
func getImageOfScrollView() -> UIImage {
var image = UIImage()
UIGraphicsBeginImageContextWithOptions(self.scrollView.contentSize, false, UIScreen.mainScreen().scale)
// save initial values
let savedContentOffset = self.scrollView.contentOffset
let savedFrame = self.scrollView.frame
let savedBackgroundColor = self.scrollView.backgroundColor
// reset offset to top left point
self.scrollView.contentOffset = CGPointZero
// set frame to content size
self.scrollView.frame = CGRectMake(0, 0, self.scrollView.contentSize.width, self.scrollView.contentSize.height)
// remove background
self.scrollView.backgroundColor = UIColor.clearColor()
// make temp view with scroll view content size
// a workaround for issue when image on ipad was drawn incorrectly
let tempView = UIView(frame: CGRectMake(0, 0, self.scrollView.contentSize.width, self.scrollView.contentSize.height))
// save superview
let tempSuperView = self.scrollView.superview
// remove scrollView from old superview
self.scrollView.removeFromSuperview()
// and add to tempView
tempView.addSubview(self.scrollView)
// render view
// drawViewHierarchyInRect not working correctly
tempView.layer.renderInContext(UIGraphicsGetCurrentContext())
// and get image
image = UIGraphicsGetImageFromCurrentImageContext()
// and return everything back
tempView.subviews[0].removeFromSuperview()
tempSuperView?.addSubview(self.scrollView)
// restore saved settings
self.scrollView.contentOffset = savedContentOffset
self.scrollView.frame = savedFrame
self.scrollView.backgroundColor = savedBackgroundColor
UIGraphicsEndImageContext()
return image
}
Run Code Online (Sandbox Code Playgroud)
Roo*_*tal 10
处理UIScrollView的UIView扩展的工作示例:
extension UIView {
func screenshot() -> UIImage {
if(self is UIScrollView) {
let scrollView = self as! UIScrollView
let savedContentOffset = scrollView.contentOffset
let savedFrame = scrollView.frame
UIGraphicsBeginImageContext(scrollView.contentSize)
scrollView.contentOffset = .zero
self.frame = CGRect(x: 0, y: 0, width: scrollView.contentSize.width, height: scrollView.contentSize.height)
self.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
scrollView.contentOffset = savedContentOffset
scrollView.frame = savedFrame
return image!
}
UIGraphicsBeginImageContext(self.bounds.size)
self.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
Run Code Online (Sandbox Code Playgroud)
我从@Roopesh Mittal采取了上述解决方案,使其更安全/更清洁.
Swift 4兼容
fileprivate extension UIScrollView {
func screenshot() -> UIImage? {
let savedContentOffset = contentOffset
let savedFrame = frame
UIGraphicsBeginImageContext(contentSize)
contentOffset = .zero
frame = CGRect(x: 0, y: 0, width: contentSize.width, height: contentSize.height)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
contentOffset = savedContentOffset
frame = savedFrame
return image
}
}
Run Code Online (Sandbox Code Playgroud)
在 iOS 13 中,我遇到了这条线不起作用的问题
frame = CGRect(x: 0, y: 0, width: contentSize.width, height: contentSize.height)
为了解决这个问题,我正在从父级中删除滚动视图,然后在截取屏幕截图后附加。
完整代码:
func screenshot() -> UIImage? {
let savedContentOffset = contentOffset
let savedFrame = frame
defer {
contentOffset = savedContentOffset
frame = savedFrame
}
contentOffset = .zero
frame = CGRect(x: 0, y: 0, width: contentSize.width, height: contentSize.height)
let image = UIGraphicsImageRenderer(bounds: CGRect(origin: .zero, size: contentSize)).image { renderer in
let context = renderer.cgContext
layer.render(in: context)
}
return image
}
Run Code Online (Sandbox Code Playgroud)
获取截图:
func getScreenshot() -> UIImage? {
scrollView.removeFromSuperview()
let image = scrollView.screenshot()
addScrollView()
return image
}
Run Code Online (Sandbox Code Playgroud)
经过改进的Swift 4.x / 5.0版本,基于@RyanG的答案:
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
}
}
Run Code Online (Sandbox Code Playgroud)