Как сделать снимок текущего экрана и использовать его в коде? (iPhone SDK) - PullRequest
11 голосов
/ 18 мая 2009

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

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

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

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

Единственный другой вариант, который я могу придумать, - это возвращать NO для всех ориентаций, кроме моей по умолчанию, а затем реагировать, применяя мои собственные анимации и преобразования. Однако я бы предпочел использовать систему для этого, так как я чувствую, что, скорее всего, это делает сам, что может вызвать «неопределенное» поведение клавиатуры в представлении, повернутом вручную, и т. Д.

Мысли

Ответы [ 4 ]

21 голосов
/ 22 ноября 2009
- (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

12 голосов
/ 16 августа 2011

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

- (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 голосов
/ 18 мая 2009

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

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

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

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

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

1 голос
/ 28 мая 2009

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

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

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

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

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

...