UIGraphicsGetCurrentContext and UIScrollView

2019-08-25 14:04发布

问题:

I'm trying to save all of the contents of a UIScrollView to a .pdf. I found some tutorials for saving the current view, and they all rely on creating a CGContextRef using UIGraphicsGetCurrentContext(). Right now, I capture my view with just

CGContextRef context = UIGraphicsGetCurrentContext();
[myView.layer renderInContext:context];

And that works fine for a plain UIView. However, when I try to pass a UIScrollView as myView, it passes the visible part of the UIScrollView fine, but anything offscreen is just white space. Is there a way I can expand context somehow to get all of the content in my UIScrollView, and not just what is currently visible? I suspect that I can't use UIGraphicsGetCurrentContext() for a UIScrollView, but I don't know what to use instead, and the Apple docs on this aren't really very helpful.

回答1:

If you have a subview taking the whole content size of the scrollView with the scrolling content you can do it like this:

CGContextRef context = UIGraphicsGetCurrentContext();
UIView *contentView = [scrollView subviews][0];
[contentView.layer renderInContext:context];

If there are multiple views in the scrollView you can do it like this:

UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(
                                                          scrollView.frame.origin.x,
                                                          scrollView.frame.origin.y, 
                                                          scrollView.contentSize.width, 
                                                          scrollView.contentSize.height)];
for(UIView *view in [scrollView subviews]){
 [contentView addSubview: view];
}

CGContextRef context = UIGraphicsGetCurrentContext();
[contentView.layer renderInContext:context];

Then you need to get the views back into the scrollView. Probably there is a way to copy them but I am not sure how. Anyhow here is what should work:

for(UIView *view in [contentView subviews]){
 [view removeFromSuperView];
 [scrollView addSubview:view];
}


回答2:

You can set frame of UIScrollView equal to content size of it and content offset to 0 before calling renderInContext. After that revert frame to original.

myView.frame = CGRectMake(myView.frame.origin.x,myView.frame.origin.y,myView.contentSize.with,myView.contentSize.height);


回答3:

This code i used to make pdf from uiscrollview and it does help but it will not be as good as if we draw on pdf -- please have look -- Pdf from UIScrollView

- (void) createPDF
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *directroyPath = nil;
    directroyPath = [documentsDirectory stringByAppendingPathComponent:@"temp"];
    NSString *filePath = [directroyPath stringByAppendingPathComponent:@"test.pdf"];
    // check for the "PDF" directory
    NSError *error;
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {

    } else {
        [[NSFileManager defaultManager] createDirectoryAtPath:directroyPath
                                  withIntermediateDirectories:NO
                                                   attributes:nil
                                                        error:&error];
    }

    CGContextRef pdfContext = [self createPDFContext:_scrollView2.bounds path:(CFStringRef)filePath];
    NSLog(@"PDF Context created");

    /*
     Here limit of i is no of pages in your uiscrollview or
     you can use hit and trial here because there is a
     length of page is going to be equal to 
     the visible size of uiscrollView in your application 
   */

    for (int i = 0 ; i< 2 ; i++)
    {

        // page 1
        CGContextBeginPage (pdfContext,nil);

        //turn PDF upsidedown
        CGAffineTransform transform = CGAffineTransformIdentity;

       //here 365 is equal to the height of myScrollView.frame.size.height

        transform = CGAffineTransformMakeTranslation(0, (i+1) * 365);
        transform = CGAffineTransformScale(transform, 1.0, -1.0);
        CGContextConcatCTM(pdfContext, transform);

        //Draw view into PDF
        [_scrollView2.layer renderInContext:pdfContext];
        CGContextEndPage (pdfContext);
        [_scrollView2 setContentOffset:CGPointMake(0, (i+1) * 365) animated:NO];

    }
    CGContextRelease (pdfContext);
}

- (CGContextRef) createPDFContext:(CGRect)inMediaBox path:(CFStringRef) path
{
    CGContextRef myOutContext = NULL;
    CFURLRef url;
    url = CFURLCreateWithFileSystemPath (NULL, path,
                                         kCFURLPOSIXPathStyle,
                                         false);

    if (url != NULL) {
        myOutContext = CGPDFContextCreateWithURL (url,
                                                  &inMediaBox,
                                                  NULL);
        CFRelease(url);
    }
    return myOutContext;
}


回答4:

Check ScrollViewToPDF example and understand it.

It uses same scrollview's layer renderInContext but here PDF is created according to your requirement such as one page PDF or multiple page PDF

Note : It captures all visible as well as invisible part of scrollView