Вопросы ориентации UIWindow (два пользовательских интерфейса и ландшафтный режим)

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

У меня есть два UIWindow в моем приложении. Первое – это главное окно, которое создается по умолчанию приложением. Второй называется modalWindow и также создается в modalWindow приложения.

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.modalWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.modalWindow.windowLevel = UIWindowLevelStatusBar; //Other stuff I need //.... return YES; } 

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

 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; 

Это прекрасно работает и в методе orientationChanged я представляю контроллер ландшафтного представления. На этом все хорошо. Если я вернусь назад к портрету, я снова получаю changeChanged, и в этот момент я увольняю контроллер ландшафта.

Теперь давайте объясним, как вступает в игру второе окно. Когда в ландшафтном режиме есть действие (просто нажатие кнопки), которое представляет новый контроллер просмотра во втором окне ( modalWindow ). Хорошо, давайте объясним это.

У делегата приложения есть два метода, которые выглядят так:

 - (void)presentActivityOnModalWindow:(UIViewController *)viewController { self.modalWindow.rootViewController = viewController; self.modalWindow.hidden = NO; } - (void)modalTransitionFinished:(NSNotification *)notif { self.modalWindow.hidden = YES; self.modalWindow.rootViewController = nil; } 

Я вызываю presentActivityOnModalWindow через presentActivityOnModalWindow [[[UIApplication sharedApplication] delegate] performSelector....] . Я знаю, что это не лучшая практика, но она отлично работает. Что касается увольнения, я использую NSNotificationCenter для отправки уведомления об увольнении. Контроллер представления, который отображается в modalWindow , поддерживает только портретный режим. Он возвращает YES в shouldAutorotate и UIInterfaceOrientationMaskPortrait в supportedInterfaceOrientations .

Хорошо объясняю, но теперь мы доходим до этой проблемы. Когда я поворачиваюсь к пейзажу, всплывает модальное окно, отбрасывает модальное окно и поворачивается назад к портрету. Главное окно все еще находится в ландшафтном режиме, и все выглядит катастрофически.

Я попытался добавить наблюдателя в window и modalWindow и внести изменения в frame и bounds и вот результаты:

 Did finish launching: window frame {{0, 0}, {320, 568}} window bounds {{0, 0}, {320, 568}} modalWindow frame {{0, 0}, {320, 568}} modalWindow bounds {{0, 0}, {320, 568}} Rotate to landscape: window frame {{0, 0}, {568, 320}} Open activity in landscape: modalWindow frame {{0, 0}, {320, 568}} modalWindow frame {{0, 0}, {320, 568}} Dismiss activity: none Rotate back to portrait: none 

Так как кажется, что мое window не возвращается к нормальному кадру, когда мы вернемся в портретный режим. Как это исправить? Если мне нужно предоставить более подробную информацию, не стесняйтесь спрашивать.

Система будет обрабатывать вращение вашего keyWindow . Если у вас есть другие окна, вам придется самостоятельно управлять поворотом.

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

https://github.com/search?o=desc&q=uialertview&s=stars&type=Repositories&utf8=

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

 self.modalWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 

Представление UIViewController модально выполняется из экземпляра UIViewController используя

 [self presentViewController:<#(UIViewController *)#> animated:<#(BOOL)#> completion:<#^(void)completion#>] 

Вы создаете 2 окна, и Apple рекомендует против этого. В приложении должно быть так много окон, как есть устройства отображения. ( SEE UIWindow reference )

Я бы предложил использовать 2 вида и «рисовать» все на этих представлениях в соответствии с ориентацией. Затем сделайте один вид скрытым, когда отображается другое.

В качестве альтернативы вы можете просто использовать 1 представление и вносить коррективы во время изменений ориентации. Легкость в этом зависит от типа отображаемой информации. Изменения ориентации лучше всего обнаруживаются с помощью кода AppDelegate.

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

 - (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation { //other stuff from rotate: UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; CGRect appFrame = [[UIScreen mainScreen ]applicationFrame];//using frame so status bar is not part of calculations. if (orientation == UIInterfaceOrientationLandscapeRight || orientation == UIInterfaceOrientationLandscapeLeft ) { self.currentAppScreenWidth = appFrame.size.height; self.currentAppScreenHeight = appFrame.size.width; [YOURapp reArrangeSubViews_and_Layouts: appFrame];//Something like this - maybe. } else { self.currentAppScreenWidth = appFrame.size.width; self.currentAppScreenHeight = appFrame.size.height; [YOURapp reArrangeSubViews_and_Layouts: appFrame];//Something like this - maybe. } } 

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

[Возможно, еще немного информации о различиях в данных, отображаемых на 2 экранах, если вышеупомянутое решение не работает для вас. Приветствия.]

  • keyWindow не всегда возвращает UIWindow
  • проблема с отображением другого UIWindow
  • Добавить вид между строкой состояния и панель навигации
  • Добавление подуровня CALayer внутри UIView init
  • Представление «прыгает», когда я добавляю его в UIWindow как subview (через свойство rootViewController) и делаю флип
  • Закрашенное вращение интерфейса при использовании второго UIWindow с rootViewController
  • UIWindow удалить ошибку в iOS9.1
  • Создание кнопки на всех контроллерах представлений
  • Созданный вручную UIWindow - это неправильный размер
  • iOS 8/7 UIWindow с проблемой вращения UIWindowLevelStatusBar
  • События iOS - UIEventTypeRemoteControl не получены
  • Давайте будем гением компьютера.