I have a method I use to get images from a various views in my iOS application for letting users email screens. Most of the screens where I draw are working ok, but when I u
You could zoom the uiwebview out so that all content fits on the screen...but this will only work if the image is off the screen horizontally. If the UIWebView is longer than the screen then this won't do much.
[webview.scrollView setZoomScale:webview.scrollView.minimumZoomScale animated:NO];
Wow the answer was stupidly simple... was digging all over the place looking at various Printing/PDF related stuff... then it occurred to me, why not just set the view IN THE CONTEXT to a sizeThatFits. It worked!
WARNING: No guarantee you don't run into mem issues with this and I DO suggest you do this inside an @autoreleasepool pool and consider doing some scaling as I do in the example, but THIS WORKS and is what I settled on:
-(NSData *)getImageFromView:(UIView *)view // Mine is UIWebView but should work for any
{
NSData *pngImg;
CGFloat max, scale = 1.0;
CGSize viewSize = [view bounds].size;
// Get the size of the the FULL Content, not just the bit that is visible
CGSize size = [view sizeThatFits:CGSizeZero];
// Scale down if on iPad to something more reasonable
max = (viewSize.width > viewSize.height) ? viewSize.width : viewSize.height;
if( max > 960 )
scale = 960/max;
UIGraphicsBeginImageContextWithOptions( size, YES, scale );
// Set the view to the FULL size of the content.
[view setFrame: CGRectMake(0, 0, size.width, size.height)];
CGContextRef context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
pngImg = UIImagePNGRepresentation( UIGraphicsGetImageFromCurrentImageContext() );
UIGraphicsEndImageContext();
return pngImg; // Voila an image of the ENTIRE CONTENT, not just visible bit
}
WKWebView has a more convenient way of doing it these days
Assign this delegate to the webviews navigation delegate and implement the completion handler to get the image back
class WebviewDelegate: NSObject, WKNavigationDelegate {
var completion: ((UIImage?) -> ())?
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("document.body.offsetHeight;") { (result, error) in
if let height = result as? CGFloat {
let config = WKSnapshotConfiguration()
config.rect = CGRect(x: 0, y: 0, width: webView.scrollView.contentSize.width, height: height)
webView.takeSnapshot(with: config) { (image, error) in
self.completion?(image)
}
}
}
}
}
I created a category for this a while ago. It works if (and only if) the web view is cached into memory, otherwise parts of the page will appear as white.
#import "UIWebView+Screenshot.h"
#import <QuartzCore/QuartzCore.h>
@implementation UIWebView (Screenshot)
- (UIImage *)screenshot {
UIImage *img = nil;
UIGraphicsBeginImageContextWithOptions(self.scrollView.contentSize, self.scrollView.opaque, 0.0);
{
CGPoint savedContentOffset = self.scrollView.contentOffset;
CGRect savedFrame = self.scrollView.frame;
self.scrollView.contentOffset = CGPointZero;
self.scrollView.frame = CGRectMake(0, 0, self.scrollView.contentSize.width, self.scrollView.contentSize.height);
[self.scrollView.layer renderInContext: UIGraphicsGetCurrentContext()];
img = UIGraphicsGetImageFromCurrentImageContext();
self.scrollView.contentOffset = savedContentOffset;
self.scrollView.frame = savedFrame;
}
UIGraphicsEndImageContext();
return img;
}
@end