2009-05-18 9 views
11

Próbuję przejść z jednego UIView na inny, gdy użytkownik obraca urządzenie. To samo w sobie nie jest trudne. Ponieważ jednak wyświetlana jest zupełnie inna zawartość po obrocie, domyślna animacja zapewniona przez UIKit (obracanie aktualnie wyświetlanego widoku) jest niewłaściwa koncepcyjnie.Jak przechwycić bieżący zrzut ekranu i użyć go ponownie w kodzie? (iPhone SDK)

Po prostu wyłączenie animacji i zamianę widoków nagle jest znośna, ale jest znacznie poniżej polskiej, którą buduję w pozostałej części aplikacji. To, co chciałbym zrobić, to:

Kiedy wywoływana jest nazwaAutorotateToInterfaceOrientation: chciałbym pobrać migawkę widoku nieprzezroczystego, zrzutu ekranu, jeśli wolisz, widoku użytkownika przed obrotem. Następnie po zakończeniu rotacji i zastosowaniu przez system transformacji widoku itp. Mogę wyświetlić widok migawki, który zapisałem i animować przejście z mojego wyboru do mojego nowego widoku. Po zakończeniu mogę zwolnić migawkę i przejść dalej.

Czy istnieje sposób, aby to zrobić, nie jest drogie?

Jedyna inna opcja, którą mogę wymyślić, to zwrócić NO na wszystkich orientacjach innych niż moja domyślna, a następnie zareagować, stosując własne animacje i transformacje. Wolałbym jednak użyć tego systemu, aby to zrobić, ponieważ wydaje mi się, że jest to prawdopodobne, ponieważ sam mógłbym spowodować "niezdefiniowane" zachowanie klawiatury w ręcznie obracanym widoku, itp.

Myśli?

+0

Należy zauważyć, że mam teraz próbował co wspomniałem jako drugą opcję: reakcję ręcznie zastosowanie własnych widoków i transformacja po powrocie NIE ... a klawiatura rzeczywiście pojawia się w niewłaściwej orientacji. Nie jestem w stanie naprawić tego zachowania, gdybym szedł w tym kierunku. –

Odpowiedz

1

Mogę Ci zagwarantować, że [window drawRect:] nie zadziała. Większość widoków nie implementuje drawRect: i na pewno nie jest rekursywny jak na Macu.

drawInContext: jest również w znacznym stopniu symulowany, ponieważ zasadniczo zaleca warstwie rysowanie siebie, a nie rekursywnie podwarstw. "Domyślna implementacja nic nie robi." mówi wszystko.

I to na wdrożenie aplikacji Clif Bar Save Our Śnieg w sklepie z aplikacjami, wykonując następujące czynności:

  • Spacer hierarchii warstw rekurencyjnie, uzyskiwanie zawartości z każdej warstwy. Jeśli pachnie jak obraz, użyj metod CGContext, aby narysować go w swoim kontekście.
  • Podczas spaceru, należy zastosować transformacje/pozycje każdej warstwy, jak zadzwonić rekursywnie

Tak, to dość duży ból w dupie. Ale tak, działa całkiem nieźle i przeszedł przez Apple :).

4

Na Macu to takie łatwe ... wystarczy -bitmapImageRepForCachingDisplayInRect:, ale iPhone oczywiście nie ma czegoś takiego.

Myślę, że zaatakowałbym to, ustawiając kontekst graficzny i wywołując na nim [window drawRect:...], aby uchwycić bieżący obraz ekranu. Jest to trochę poza specyfikacją, ponieważ nie powinieneś sam dzwonić pod numer -drawRect:. Byłbym trochę zdenerwowany działaniem ubocznym, ale może to być w porządku. Jeśli kontrolujesz widok pełnoekranowy, możesz oczywiście wyciągnąć kod rysunkowy z numeru -drawRect:, więc nie wywołujesz go bezpośrednio.

Podobnym podejściem byłoby użycie CALayer -drawInContext: obecnego . To może być trochę więcej "w spec", ponieważ legalne jest przekazywanie tego w swoim własnym kontekście. Ale nie wiem, czy byłbyś w stanie poprawnie uzyskać wszystkie widoki podrzędne. Może zależeć od natury twojego UIWindow.

W każdym razie świetne pytanie. Może ktoś ma bardziej sprytne rozwiązanie, ale w ten sposób go zaatakuję.

EDIT: Dzięki Rob Terrell, a jego mądre UIApplication+TVOut.m, I został wprowadzony do prywatnej metody UIGetScreenImage(), która zwraca CGImageRef. Jeśli chcesz skorzystać z prywatnych metod, jest to dla ciebie dobra opcja. Biorąc pod uwagę jego nazwę i funkcjonalność, wygląda na całkiem stabilną i wydaje mi się, że nie jest to zgodne z intencją Apple. Wpadłem też na niezłą dyskusję na temat Air Source. Przeczytaj komentarze do kilku linków.

+0

Jeśli chcesz publikować w App Store, użycie UIGetScreenImage() spowoduje odrzucenie Twojej aplikacji. –

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

Znalazłem to tutaj:

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

+0

wspaniałe znalezisko, działa idealnie. – Rog

+1

Istnieje duży problem z tym podejściem: 'UIGraphicsGetImageFromCurrentImageContext()' wycieka pamięć (UIImage, którą tworzy, nigdy nie jest prawidłowo utylizowana), przynajmniej w starszych wersjach systemu operacyjnego (5.0 wydaje się już nie mieć tego problemu). – MusiGenesis

12

Ten kod pracował dla mnie

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

Mam z tym problem. Reprezentuję obrysy na czystym tle i gdy tylko zapiszę, dodaje gdzieś czarne tło do obrazu. – manishnath

+1

Twój kod działa doskonale! – user523234

+1

Dzięki człowiekowi działa – Hiren

Powiązane problemy