Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to take screenshot of UIScrollView visible area?

How do I take a 1:1 screenshot of UIScrollView visible area? The content may be larger or smaller than UIScrollView bounds as well as half-hidden (I've implemented custom scrolling for smaller content, so it's not in the top-left corner). I've achieved desired result on simulator, but not on device itself:

-(UIImage *)imageFromCombinedContext:(UIView *)background {
      UIImage *image;
      CGRect vis = background.bounds;
      CGSize size = vis.size;
      UIGraphicsBeginImageContext(size);
      [background.layer affineTransform];
      [background.layer renderInontext:UIGraphicsGetCurrentContext()];
      image = UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();
      CGImageRef imref = CGImageCreateWithImageInRect([image CGImage], vis);
      image = [UIImage imageWithCGImage:imref];
      CGImageRelease(imref);
      return image;
}
like image 957
Concuror Avatar asked Jun 11 '12 08:06

Concuror


2 Answers

Swift version of Abduliam Rehmanius answer.

func screenshot() -> UIImage {

        UIGraphicsBeginImageContextWithOptions(self.scrollCrop.bounds.size, true, UIScreen.mainScreen().scale);
        //this is the key
        let offset:CGPoint = self.scrollCrop.contentOffset;
        CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -offset.x, -offset.y);
        self.scrollCrop.layer.renderInContext(UIGraphicsGetCurrentContext()!);
        let visibleScrollViewImage: UIImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return visibleScrollViewImage;
    }

Swift 4 version:

func screenshot() -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.scrollCrop.bounds.size, false, UIScreen.main.scale)
        let offset = self.scrollCrop.contentOffset
        let thisContext = UIGraphicsGetCurrentContext()
        thisContext?.translateBy(x: -offset.x, y: -offset.y)
        self.scrollCrop.layer.render(in: thisContext!)
        let visibleScrollViewImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
return visibleScrollViewImage
}
like image 96
Deepak Thakur Avatar answered Nov 14 '22 21:11

Deepak Thakur


Another approach would be to use the contentOffset to adjust the layer's visible area and capture only the currently visible area of UIScrollView.

UIScrollView *contentScrollView;....//scrollview instance

UIGraphicsBeginImageContextWithOptions(contentScrollView.bounds.size, 
                                       YES, 
                                       [UIScreen mainScreen].scale);

//this is the key
CGPoint offset=contentScrollView.contentOffset;
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -offset.x, -offset.y); 

[contentScrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *visibleScrollViewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Cheers :)

like image 45
Abduliam Rehmanius Avatar answered Nov 14 '22 21:11

Abduliam Rehmanius