Прозрачный Modal ViewController – как обрабатывать вращение

Я хотел бы отобразить UIViewController по UIViewController и иметь возможность увидеть размытую версию представления, которая ее представила.

Следуя ряду подобных вопросов, таких как:

iOS 7 Прозрачный контроллер Modal View

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

Я попытался захватить свежий снимок представленного viewController в didRotateFromInterfaceOrientation: модального viewController, но кажется, что пользовательский интерфейс представляющего viewController не обновляется, и результирующее изображение по-прежнему является неправильной ориентацией. Есть ли способ заставить перерисовку представления, которое скрывается от модального?

One Solution collect form web for “Прозрачный Modal ViewController – как обрабатывать вращение”

После долгих размышлений я придумал проворный способ справиться с этим. Насколько хорошо он будет работать, немного зависит от типа содержимого, которое у вас есть в представлении viewController .

Общая идея – взять не один, а два скриншота, прежде чем представить новый viewController – один для портрета, один для пейзажа. Это достигается путем изменения рамок верхнего viewController и навигационной панели (если применимо) для эмуляции другой ориентации, снятия скриншота результата и изменения его. Пользователь никогда не видит этого изменения на устройстве, но экранный захват по-прежнему отображает новую ориентацию.

Точный код будет зависеть от того, откуда вы его вызываете, но основная логика такая же. Моя реализация выполняется из AppDelegate потому что она повторно используется несколькими подклассами UIViewController .

Ниже приведен код, который будет захватывать соответствующие скриншоты.

 // get references to the views you need a screenshot of // this may very depending on your app hierarchy UIView *container = [self.window.subviews lastObject]; // UILayoutContainerView UIView *subview = container.subviews[0]; // UINavigationTransitionView UIView *navbar = container.subviews[1]; // UINavigationBar CGSize originalSubviewSize = subview.frame.size; CGSize originalNavbarSize = navbar.frame.size; // compose the current view of the navbar and subview UIImage *currentComposed = [self composeForeground:navbar withBackground:subview]; // rotate the navbar and subview subview.frame = CGRectMake(subview.frame.origin.x, subview.frame.origin.y, originalSubviewSize.height, originalSubviewSize.width); // the navbar has to match the width of the subview, height remains the same navbar.frame = CGRectMake(navbar.frame.origin.x, navbar.frame.origin.y, originalSubviewSize.height, originalNavbarSize.height); // compose the rotated view UIImage *rotatedComposed = [self composeForeground:navbar withBackground:subview]; // change the frames back to normal subview.frame = CGRectMake(subview.frame.origin.x, subview.frame.origin.y, originalSubviewSize.width, originalSubviewSize.height); navbar.frame = CGRectMake(navbar.frame.origin.x, navbar.frame.origin.y, originalNavbarSize.width, originalNavbarSize.height); // assign the variables depending on actual orientations UIImage *landscape; UIImage *portrait; if (originalSubviewSize.height > originalSubviewSize.width) { // current orientation is portrait portrait = currentComposed; landscape = rotatedComposed; } else { // current orientation is landscape portrait = rotatedComposed; landscape = currentComposed; } CustomTranslucentViewController *vc = [CustomTranslucentViewController new]; vc.backgroundSnap = portrait; vc.backgroundSnapLandscape = landscape; [rooVC presentViewController:vc animated:YES completion:nil]; 

Метод composeForeground:withBackground: метод удобства, который генерирует соответствующее фоновое изображение на основе двух входных представлений (панель навигации + контроллер просмотра). Помимо составления обоих представлений вместе, это делает немного более волшебным, чтобы сделать результат более естественным при вращении представленного viewController . В частности, он расширяет скриншот до квадрата 1024×1024 и заполняет дополнительное пространство зеркальной копией скомпонованного изображения. Во многих случаях, когда это размыто, это выглядит достаточно хорошо, поскольку анимация повторного рисования просмотров для изменения ориентации недоступна.

 - (UIImage *)composeForeground:(UIView *)frontView withBackground:(UIView *)backView { UIGraphicsBeginImageContextWithOptions(backView.frame.size, 0, 0); [backView.layer renderInContext:UIGraphicsGetCurrentContext()]; // translation is necessary to account for the extra 20 taken up by the status bar CGContextTranslateCTM(UIGraphicsGetCurrentContext(), frontView.frame.origin.x, frontView.frame.origin.y); [frontView.layer renderInContext:UIGraphicsGetCurrentContext()]; CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -frontView.frame.origin.x, -frontView.frame.origin.y); // this is the core image, would have left it at this if we did not need to use fancy mirrored tiling UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // add mirrored sections CGFloat addition = 256; // 1024 - 768 if (newImage.size.height > newImage.size.width) { // portrait, add a mirrored image on the right UIImage *horizMirror = [[UIImage alloc] initWithCGImage:newImage.CGImage scale:newImage.scale orientation:UIImageOrientationUpMirrored]; UIGraphicsBeginImageContextWithOptions(CGSizeMake(newImage.size.width+addition, newImage.size.height), 0, 0); [horizMirror drawAtPoint:CGPointMake(newImage.size.width, 0)]; } else { // landscape, add a mirrored image at the bottom UIImage *vertMirror = [[UIImage alloc] initWithCGImage:newImage.CGImage scale:newImage.scale orientation:UIImageOrientationDownMirrored]; UIGraphicsBeginImageContextWithOptions(CGSizeMake(newImage.size.width, newImage.size.height+addition), 0, 0); [vertMirror drawAtPoint:CGPointMake(0, newImage.size.height)]; } // combine the mirrored extension with the original image [newImage drawAtPoint:CGPointZero]; newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // for ios 6, crop off the top 20px if (SYSTEM_VERSION_LESS_THAN(@"7")) { UIGraphicsBeginImageContextWithOptions(CGSizeMake(newImage.size.width, newImage.size.height-20), NO, 0); [newImage drawAtPoint:CGPointMake(0, -20)]; newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); } return newImage; } 

Полученные пейзажные и портретные изображения могут быть размыты и затемнены по желанию и заданы в качестве фона для представленного viewController . Используйте willRotateToInterfaceOrientation:duration: метод этого viewController для выбора соответствующего изображения.

Примечание . Я попытался как можно больше уменьшить объем работы, выполняемой на изображениях и графических контекстах, но при генерации фона (около 30-90 мс на composeForeground:withBackground: iteration, в зависимости от содержимого , на старинном медленном iPad 2). Если вы знаете способ дальнейшей оптимизации или упрощения вышеуказанного решения, пожалуйста, поделитесь!

  • Отобразить clearColor UIViewController над UIViewController
  • Создание первого диспетчера просмотра запуска
  • Является ли UIViewController beginAppearanceTransition: анимированный: метод доступен в iOS5
  • исключить плохой код доступа 2
  • Выражение типа ? не использовался
  • Как нажать с контроллера вида на контроллер навигационного представления, используя метод prepareForSegue?
  • Получить контейнер VC вместо просмотра
  • Отключить контроллер просмотра при нажатии кнопки «Домой»
  • ОтклонитьModalViewController от другого modalViewController
  • CGAffineTransform - CGPoint в CGRect
  • Восстановление состояния iOS, отбрасывающее навигационный стек
  • Interesting Posts

    Получение всех контактов в ios Swift?

    Как получить все имена действий в редакторе действий Xcode в файле sks «Действие SpriteKit»

    Что такое браузер, используемый cordova на iOS?

    Подклассификация MKGeodesicPolyline

    Как подавить -Wno-протокол на файл

    Как создать пользовательский вид аннотации контактов

    Firebase Быстрый эквивалент push ()

    UITableView не будет возвращаться после прокрутки вниз по экрану

    Индикатор выполнения (и статус активности сети) для UIWebView

    Доступ к различным представлениям внутри UITableViewCell по тегу в Swift

    Напишите текст на сфера поверхности SceneKit?

    Есть ли какой-либо элемент управления, который может показывать фотографии, такие как «Фотографии» в iOS?

    Получение информации о глифе в основном тексте

    У меня есть 2 заявления в одном, первое пропускается, почему?

    Как перейти от раскадровки iPhone / iPad к универсальной раскадровке

    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.