Как захватить текущий снимок экрана и повторное использование кода? (iPhone SDK)

Я пытаюсь перейти от одного UIView к другому, когда пользователь поворачивает устройство. Это само по себе не сложно. Однако, поскольку я показываю совершенно другое содержимое после вращения, анимация по умолчанию, предоставляемая UIKit (вращение отображаемого в настоящее время вида), концептуально неприемлема.

Простое отключение анимации и замена взглядов внезапно переносимы, но намного ниже польский, который я создаю для остальной части приложения. Я бы предпочел сделать это:

При вызове функцииAutorotateToInterfaceOrientation: я хотел бы получить непрозрачный снимок зрения, скриншот, если вы захотите, перед просмотром пользователя перед ротацией. Затем, после того, как ротация завершена, и система применила преобразования вида и т.д., Я могу показать снимок, который я сохранил, и анимировать переход по своему выбору к новому представлению. После того, как он будет завершен, я могу освободить свой снимок и перейти дальше.

Есть ли способ сделать это, что не дорого?

Единственный другой вариант, о котором я могу думать, - это вернуть NO во все ориентации, отличные от моего по умолчанию, а затем отреагировать, применив мои собственные анимации и преобразования. Я предпочел бы использовать систему, чтобы сделать это, однако, поскольку я чувствую, что это возможно, это может привести к поведению клавиатуры "undefined" в ручном просмотре и т.д.

Мысли?

Ответ 1

Я могу гарантировать вам [window drawRect:] не будет работать. Большинство просмотров не реализуют drawRect: и это, конечно, не рекурсивно, как на mac.

drawInContext: также довольно сильно сидит за спиной, так как он в корне просит слой рисовать сам, а не его подслои рекурсивно. "Реализация по умолчанию ничего не делает". говорит все.

Я реализую это для приложения Cliff Bar Save Our Snow в магазине приложений, выполнив следующие действия:

  • Проведите иерархию слоев рекурсивно, получая содержимое из каждого слоя. Если он пахнет изображением, используйте методы CGContext, чтобы привлечь его в свой контекст.
  • Во время ходьбы убедитесь, что применяете преобразования/положения каждого слоя, когда вы вызываете рекурсивно

Да, довольно большая боль в заднице. Но да, это работает очень хорошо и прошло через Apple:).

Ответ 2

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

Найдено здесь:

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

Ответ 3

Этот код работал у меня

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

Ответ 4

На Mac это так просто... вам просто нужно -bitmapImageRepForCachingDisplayInRect:, но, конечно, iPhone не имеет такой вещи.

Я думаю, что я бы напал на это, установив графический контекст и набрав [window drawRect:...] на нем, чтобы захватить текущее изображение экрана. Это немного из спецификации, потому что вы действительно не должны называть -drawRect: самостоятельно. Я бы немного нервничал из-за побочных эффектов, но это может быть хорошо. Если вы контролируете весь экран, вы можете, конечно, вытащить код рисования из -drawRect:, чтобы вы не вызывали его напрямую.

Аналогичным подходом было бы использовать CALayer -drawInContext: текущего -presentationLayer. Это может быть немного больше "в спецификации", так как законно передавать этот собственный контекст. Но я не знаю, сможете ли вы правильно получить все подзадачи. Возможно, это зависит от характера вашего UIWindow.

В любом случае, большой вопрос. Возможно, у кого-то есть более умное решение, но так я бы напал на него.

EDIT: Спасибо Роб Террелл и его умный UIApplication + TVOut.m, я был представлен  для частного метода UIGetScreenImage(), который возвращает CGImageRef. Если вы готовы пойти на частные методы, это хороший вариант для вас. Учитывая его название и функциональность, он выглядит довольно стабильным для меня и вряд ли нарушит намерения Apple. Я также столкнулся с довольно приятным обсуждением Источник воздуха. Прочитайте комментарии по нескольким ссылкам.