2012-06-11 12 views
11

Wie nehme ich einen 1: 1-Screenshot von UIScrollView sichtbaren Bereich? Der Inhalt kann größer oder kleiner als die UIScrollView-Grenzen sein oder halb verborgen (ich habe ein benutzerdefiniertes Scrollen für kleinere Inhalte implementiert, so dass es nicht in der oberen linken Ecke ist). Ich habe gewünschtes Ergebnis auf Simulator erreicht, aber nicht auf dem Gerät selbst:Wie screenshot von UIScrollView sichtbaren Bereich zu machen?

-(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; 
} 

Antwort

4

Ich habe eine Lösung selbst gefunden - ich Screenshot der ganzen Sicht nahm und sich dann zuschneiden auf die Größe und die Position des UIScrollView Rahmen .

-(UIImage *)imageFromCombinedContext:(UIView *)background 
{ 
     UIImage *image; 
     CGSize size = self.view.frame.size; 
     UIGraphicsBeginImageContext(size); 
     [background.layer affineTransform]; 
     [self.view.layer.layer renderInContext:UIGraphicsGetCurrentContext()]; 
     image = UIGraphicsGetImageFromCurrentImageContext(); 
     UIGraphicsEndImageContext(); 
     CGImageRef imgRef = CGImageCreateWithImageInRect([image CGImage],background.frame); 
     image = [UIImage imageWithCGImage:imref]; 
     CGImageRelease(imref); 
     return image; 
} 
+0

akzeptieren Ihre Antwort dann :) – ant

+0

Ich muss immer noch 20 Stunden warten) – Concuror

+2

Ist das nicht schrecklich ineffic ient für große Scroll-Ansichten? Was ist los mit der Antwort von @AbduliamRehmanius Antwort? – deanWombourne

29

Ein anderer Ansatz wäre, die contentOffset verwendet die Ebene der sichtbaren Bereich einzustellen und nur den aktuell sichtbare Bereich UIScrollView zu erfassen.

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(); 

Prost :)

+3

Dies ist viel einfacher und speicheroptimiert, da kein größeres Bild geschnitten werden muss. –

+1

Diese Antwort ist die einzige, die für mich arbeitete. Vielen Dank. –

+0

Wer hat Glück auf Swift?Ich habe einen "zoombar" Scrollview, diese Erweiterung Funktion aufrufen und ein leeres Bild bekommen: func Screenshot() -> UIImage { let offset = self.contentOffset UIGraphicsBeginImageContextWithOptions (self.bounds.size, falsch, UIScreen.mainScreen() .scale) CGContextTranslateCTM (UIGraphicsGetCurrentContext(), -offset.x, -offset.y) self.layer.renderInContext (UIGraphicsGetCurrentContext()!) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return Bild } – Ryan

0

@Abduliam Rehmanius Antwort schlechte Leistung hat, da, wenn die UIScrollView einen großen Content-Bereich enthält, werden wir diesen ganzen Inhaltsbereich (auch außerhalb der sichtbaren Grenzen) ziehen. @ Concurors Antwort hat das Problem, dass es auch alles zeichnen wird, das auf dem UIScrollView steht.

Meine Lösung war die UIScrollView innerhalb eines UIView genannt containerView mit den gleichen Grenzen zu setzen und dann machen containerView:

containerView.renderInContext(context) 
3

Jeffery Sun hat die richtige Antwort. Stellen Sie Ihre Bildlaufansicht in eine andere Ansicht. Holen Sie die Containeransicht zum Rendern im Kontext. erledigt.

Im folgenden Code enthält cropView die zu erfassende Bildlaufansicht. Die Lösung ist wirklich so einfach.

Wie ich die Frage verstehe und warum ich diese Seite gefunden habe, ist der gesamte Inhalt der Bildlaufansicht nicht erwünscht - nur der sichtbare Teil.

func captureCrop() -> UIImage { 
    UIGraphicsBeginImageContextWithOptions(self.cropView.frame.size, true, 0.0) 
    self.cropView.layer.renderInContext(UIGraphicsGetCurrentContext()) 
    let image = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 
    return image; 
} 
3

Schnelle Version von Abduliam Rehmanius Antwort.

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; 
    } 
0

Swift 3.0:

func captureScreen() -> UIImage? { 
    UIGraphicsBeginImageContextWithOptions(self.yourScrollViewName.bounds.size, true, UIScreen.main.scale) 
    let offset:CGPoint = self.yourScrollViewName.contentOffset; 
    UIGraphicsGetCurrentContext()!.translateBy(x: -offset.x, y: -offset.y); 
    self.yourScrollViewName.layer.render(in: UIGraphicsGetCurrentContext()!) 
    let image = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 
    return image 
} 

und verwenden Sie es als: let Bild = Capture()

0

Update-swift 3+, 4 auf @Concuror Code

func getImage(fromCombinedContext background: UIView) -> UIImage { 
     var image: UIImage? 
     let size: CGSize = view.frame.size 
     UIGraphicsBeginImageContext(size) 
     background.layer.affineTransform() 
     view.layer.render(in: UIGraphicsGetCurrentContext()!) 
     image = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 
     let imgRef = image?.cgImage?.cropping(to: background.frame) 
     image = UIImage(cgImage: imgRef!) 
     // CGImageRelease(imgRef!) // Removing on Swift - 'CGImageRelease' is unavailable: Core Foundation objects are automatically memory managed 
     return image ?? UIImage() 
    } 
Verwandte Themen