fmas fmas - 5 months ago 23
Swift Question

Content of scrollview clear when taking screenshot

I have a scrollview and i need a screenshot of the complete content of that scrollview, i search and try many solutions on stackoverflow but that provide only the screenshot of the total height of the viewcontroller.
For example if the height of the scrollview is 1096 and Viewcontroller height is 532 , it screenshot the content according to the Viewcontroller height
I found only this code useful on stackoverflow and it return the complete height of the scrollview but it clear the content of scrollview in the Viewcontroller. Any help how to retain the content of scrollview or any better solution to take a complete screenshot in swift. Thankyou

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
}

Answer

Using this as I guide, I think you can snapshot any view using:

func snapShot(view:UIView) -> UIImage
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, true, 0)
    view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return image
}

Though with a scroll view this will only return an image of what's visible in the scroll view's frame, so we can create a helper function:

func snapShotScrollView(scrollView:UIScrollView) -> UIImage
{
    let bounds = scrollView.bounds
    scrollView.bounds.size = scrollView.contentSize
    let image = snapShot(scrollView)
    scrollView.bounds = bounds
    return image
}

This will briefly adjust our scroll view's bounds to it's content size.

I don't know how performant this code is, but this works for me in a swift playground. For example, running this code:

let scrollView = UIScrollView(frame:CGRect(x: 0.0, y: 0.0, width: 200.0, height: 200.0))
scrollView.backgroundColor = UIColor.whiteColor()
scrollView.contentSize = CGSize(width: 600.0, height: 600.0)
let blueView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 200.0, height: 200.0))
blueView.backgroundColor = UIColor.blueColor()

let redView = UIView(frame: CGRect(x: 200.0, y: 200.0, width: 400.0, height: 600.0))
redView.backgroundColor = UIColor.redColor()
scrollView.addSubview(blueView)
scrollView.addSubview(redView)
let image = snapShotScrollView(scrollView)

Results in enter image description here where as calling snapShot by itself only returns a blue square. After the snapshot the scroll view is the original size with the original content.

Comments