How to get ENTIRE image from UIWebView including offscreen content

后端 未结 4 1993
醉酒成梦
醉酒成梦 2021-01-06 16:55

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

相关标签:
4条回答
  • 2021-01-06 17:22

    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];
    
    0 讨论(0)
  • 2021-01-06 17:28

    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
    }
    
    0 讨论(0)
  • 2021-01-06 17:28

    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)
                    }
                }
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-06 17:32

    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
    
    0 讨论(0)
提交回复
热议问题