Прозрачный 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). Если вы знаете способ дальнейшей оптимизации или упрощения вышеуказанного решения, пожалуйста, поделитесь!

  • Swift - отклонение контроллера просмотра из блока завершения
  • Совместное использование того же UIViewController как rootViewController с двумя UINavigationControllers
  • передавать данные для просмотра контроллера с помощью раскадровки segue iOS
  • Как узнать, представлен ли UIVIewController в виде Peek Preview Controller
  • Черная полоса, появляющаяся в UIWebview при изменении ориентации устройства
  • Передача делегата другому делегату диспетчера представлений
  • IOS: открыть и закрыть некоторые контроллеры представлений
  • Почему UIPageViewController изменяет размеры просмотров UIViewControllers после поворота страницы?
  • Как изменить размер представления при использовании UINavigationController setToolbarHidden: анимированный:
  • Подкласс ViewController из раскадровки
  • Как добавить правую кнопку в панель навигации?
  • Interesting Posts

    Как обрабатывать временные события в iOS?

    Создайте строку с n пробелами или другим повторяющимся символом

    Protobuf против двоичных дисков для сетевой торговли в iOS-игре

    MKMapview влияет на отображение UINavigationBar и TabBar

    Xcode 7.3 Операция не может быть выполнена (ошибка LaunchServicesError 0)

    «Этот класс не является ключевым значением, совместимым с кодировкой для ключа»

    Как я могу программно включить режим «Уход» (режим киоска) на iPhone?

    Совместное использование документов iCloud между приложениями

    iOS: обнаружение, когда устройство Bluetooth отключается, когда приложение не работает

    Исключение броска UIWebView для

    Используя длинный жест нажатия, чтобы переупорядочить ячейки в виде таблицы?

    Не удается удалить приложение из iOS Simulator

    didUpdateLocations никогда не называли быстрыми

    в Objective-C, как получить доступ к частной собственности из категории

    Планирование плагина камеры с прозрачным наложением

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