Wie kann man Screenshots der aktuellen Ansicht erfassen und im Code wiederverwenden? (iPhone SDK)

Ich versuche, von einer UIView zu einer anderen zu wechseln, wenn der Benutzer das Gerät dreht. Dies ist an sich nicht schwierig. Da ich nach der Rotation jedoch völlig unterschiedliche Inhalte anzeigen werde, ist die von UIKit bereitgestellte Standardanimation (Drehen der aktuell angezeigten Ansicht) konzeptuell nicht geeignet.

Einfach die Animation zu deaktivieren und die Ansichten zu tauschen ist erträglich, aber ist weit unter der Politur, die ich in den Rest der App aufbaue. Was ich am liebsten machen würde ist:

Wenn shouldAutorotateToInterfaceOrientation: aufgerufen wird, möchte ich einen opaken Ansichtssnapshot, einen Screenshot des Benutzers vor der Rotation betrachten. Nachdem die Drehung abgeschlossen ist und das System die Ansichtsumwandlungen usw. angewendet hat, kann ich die gespeicherte Schnappschussansicht anzeigen und einen Übergang meiner Wahl in meine neue Ansicht animieren. Nachdem es fertig ist, kann ich meinen Schnappschuss freigeben und weitermachen.

Gibt es eine Möglichkeit, dies zu tun, die nicht teuer ist?

Die einzige andere Option, die ich mir vorstellen kann, ist, dass Sie NO auf alle anderen Orientierungen zurückgeben als meine Standard-Ausrichtung und dann reagieren, indem Sie meine eigenen Animationen und Transformationen anwenden. Ich würde es jedoch vorziehen, das System dazu zu verwenden, da es wahrscheinlich ist, dass es selbst zu einem “undefinierten” Verhalten der Tastatur in der manuell gedrehten Ansicht usw. führen könnte.

Gedanken?

Ich kann dir garantieren [window drawRect:] wird nicht funktionieren. Die meisten Ansichten implementieren drawRect nicht: und es ist sicherlich nicht rekursiv wie auf dem Mac.

drawInContext: wird auch ziemlich häufig abgespritzt, da es die Ebene grundsätzlich dazu auffordert, sich selbst zu zeichnen, nicht ihre Sublayer rekursiv. “Standardimplementierung tut nichts.” das sagt alles.

Ich implementiere dies für die Clif Bar Speichern Sie unsere Schnee-App im App Store, indem Sie Folgendes tun:

  • Verfolgen Sie die Ebenenhierarchie rekursiv und holen Sie sich den Inhalt jeder Ebene. Wenn es wie ein Bild riecht, verwenden Sie die CGContext-Methoden, um es in Ihren Kontext zu zeichnen.
  • Achten Sie beim Gehen darauf, die Transformationen / Positionen jeder Ebene beim rekursiven Aufruf anzuwenden

Ja, ein ziemlich großer Schmerz in den Arsch. Aber ja, es funktioniert ziemlich gut und ist von Apple durchgekommen :).

- (UIImage *)captureView:(UIView *)view { CGRect screenRect = [[UIScreen mainScreen] bounds]; UIGraphicsBeginImageContext(screenRect.size); CGContextRef ctx = UIGraphicsGetCurrentContext(); [[UIColor blackColor] set]; CGContextFillRect(ctx, screenRect); [view.layer renderInContext:ctx]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 

Gefunden hier:

http://discussions.apple.com/thread.jspa?messageID=8358740

Dieser Code hat für mich funktioniert

 - (UIImage *)captureScreenInRect:(CGRect)captureFrame { CALayer *layer; layer = self.view.layer; UIGraphicsBeginImageContext(self.view.bounds.size); CGContextClipToRect (UIGraphicsGetCurrentContext(),captureFrame); [layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *screenImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return screenImage; } 

Auf dem Mac ist das so einfach … Sie brauchen nur -bitmapImageRepForCachingDisplayInRect: aber natürlich hat das iPhone so etwas nicht.

Ich denke, ich würde dies angreifen, indem ich einen Grafikkontext [window drawRect:...] und [window drawRect:...] darauf [window drawRect:...] , um das aktuelle Bild des Bildschirms zu erfassen. Dies ist ein bisschen außerhalb der Spezifikation, weil du nicht wirklich zum Aufruf von -drawRect: dir selbst gehen -drawRect: . Ich wäre etwas nervös wegen der Nebenwirkungen, aber das könnte gut sein. Wenn es sich um eine Vollbildansicht handelt, die Sie steuern, können Sie den Zeichnungscode natürlich aus -drawRect: Sie rufen das also nicht direkt an.

Ein ähnlicher Ansatz wäre die Verwendung von CALayer -drawInContext: der aktuellen- -presentationLayer . Das könnte etwas mehr “in spec” sein, da es legal ist, diesen eigenen Kontext zu bestehen. Aber ich weiß nicht, ob Sie tatsächlich alle Unteransichten richtig erhalten könnten. Könnte von der Art Ihres UIWindow abhängen.

Wie auch immer, gute Frage. Vielleicht hat jemand eine cleverere Lösung, aber so würde ich es angreifen.

EDIT: Dank Rob Terrell und seiner cleveren UIApplication + TVOut.m wurde ich in die private Methode UIGetScreenImage () eingeführt, die einen CGImageRef zurückgibt. Wenn Sie bereit sind, zu privaten Methoden zu gehen, ist das eine gute Option für Sie. Angesichts seines Namens und seiner functionalität sieht es für mich ziemlich stabil aus und scheint Apples Absicht nicht zu verletzen. Ich habe auch eine ziemlich nette Diskussion über Air Source gemacht . Lesen Sie die Kommentare für mehrere Links.