2015-02-20 1 views
5

Я знаю, что это выглядит как огромный вопрос, но не так, не бойтесь его прочитать. В основном это объясняет, как работает материал.Проблемы ориентации UIWindow (два режима UIWindows и ландшафта)

У меня есть два UIWindow s в моем приложении. Первое - это главное окно, которое создается по умолчанию приложением. Второй - 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 я представляю контроллер представления ландшафта. На этом все хорошо. Если я вернусь к портрету, я снова получаю orientationChanged, и в этот момент я увольняю контроллер ландшафтного вида.

Теперь давайте объясним, как вступает в игру второе окно. Когда в ландшафтном режиме есть действие (просто нажатие кнопки), которое представляет новый контроллер просмотра во втором окне (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 через [[[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 не вернется к обычному режиму кадра, когда мы получаем обратно в портретный режим. Как это исправить? Если мне нужно предоставить более подробную информацию, не стесняйтесь спрашивать.

ответ

1

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

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

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

-1

Вы создаете 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 экранах, если указанное выше решение не работает для вас. Cheers.]

0

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

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

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

[self presentViewController:<#(UIViewController *)#> animated:<#(BOOL)#> completion:<#^(void)completion#>] 
Смежные вопросы