Подтвердить что ты не робот

Просмотр поверх всего: UIWindow subview VS UIViewController subview

Чтобы сделать UIView поверх всех представлений, таких как поведение UIAlertView, лучший способ, который я вижу, - поместить его в окно приложения, которое добавляет представление в:

[[[UIApplication sharedApplication] delegate] window]

Однако недостаток, который я обнаружил, заключается в том, что он автоматически не принимает вращения. Для того, чтобы он принимал во вращение, лучший способ сделать это, добавив представление в текущий AppDelegate window.navigationController/rootViewController, тем не менее, сделав это, он больше не будет поверх всего. Пусть говорят, что когда отображается представление, и появляется всплывающее окно modalViewController, модальное представление наверняка прикроет вид.

Мой вопрос в том, можно ли добавить subview в самое верхнее окно и поддерживать ориентацию? В этом случае мне нужен два набора файлов Nib? Как UIAlertView делает магию комбинацией максимальной и ориентированной поддержки? Когда я смотрю в UIAlertView.h, я вижу, что на самом деле есть 2 UIWindows, один раз называется originalWindow, а другой - dimWindow. Есть ли место, где я могу найти исходный код для UIAlertView.m?

4b9b3361

Ответ 1

Лучшим решением, которое я нашел, является создание прозрачного представления контейнера, добавление этого контейнера в окно и размещение вашего предупреждения внутри контейнера. Затем вы можете зарегистрироваться для UIApplicationWillChangeStatusBarOrientationNotification для получения событий поворота и преобразования контейнера; это позволяет вам самостоятельно управлять рамкой оповещения:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{
     ...
     self.container = [[UIView alloc] initWithFrame:self.window.bounds];
     [self.container addSubview:self.alertView];
     [self.window addSubview:self.container];
     [[NSNotificationCenter defaultCenter] addObserver:self 
                                              selector:@selector(statusBarWillRotate:) 
                                                  name:UIApplicationWillChangeStatusBarOrientationNotification 
                                                object:nil];
     ...
}
...
- (void)statusBarWillRotate:(NSNotification *)theNotification
{
    CGFloat rotation = 0;
    switch ([notification[UIApplicationStatusBarOrientationUserInfoKey] intValue])
    {
        case UIInterfaceOrientationLandscapeLeft:
            rotation = -M_PI_2;
            break;
        case UIInterfaceOrientationLandscapeRight:
            rotation = M_PI_2;
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            rotation = M_PI;
            break;
        case UIInterfaceOrientationPortrait: 
        default:
            rotation = 0;
            break;
    }
    CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(rotation);
    CGSize rotatedSize = CGRectApplyAffineTransform(self.window.bounds, rotationTransform).size;
    [UIView animationWithDuration:[UIApplication sharedApplication].statusBarOrientationAnimationDuration
                       animations:^{
         self.container.transform = rotationTransform;
         // Transform invalidates the frame, so use bounds/center
         self.container.bounds = CGRectMake(0, 0, rotatedSize.width, rotatedSize.height);
         self.container.center = CGPointMake(self.window.bounds.size.width / 2, self.window.bounds.size.height / 2);
     }];
}

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

Проблема с простое добавлением вида контроллера просмотра в окно заключается в том, что он не гарантирует получение всех сообщений вращения и view[Will|Did][Disa|A]ppear:, если он не добавлен в иерархию диспетчера представлений через addChildViewController: на контроллере корневого представления.

Ответ 2

Сообщается только о первом подсмотре UIWindow об изменениях ориентации. (< iOS8)

Ваш вопрос очень похож на этот:

Несколько видов в UIWindow

Как говорится в ответе, вы можете зарегистрироваться для уведомлений об изменении ориентации и обработать ретрансляцию своего "сверху" подпрограммы таким образом.

Ответ 3

Вот возможное решение, я объясняю в несколько шагов.

  • Начните с UIViewController унаследованного класса вместо UIView, скажем, класс с именем TopViewController, унаследованный UIViewController
  • Поскольку вы не можете зарегистрировать вращение устройства/интерфейса в унаследованном классе UIView, класс TopViewController, унаследованный от UIViewController, имеет методы, относящиеся к событиям просмотра поворота. События поворота могут быть захвачены сейчас.
  • Наконец, вы можете разместить представление TopViewController в верхней части UIWindow, используя тот же метод, что и вы упомянули в своем вопросе.

    [[[[UIApplication sharedApplication] delegate] window] addSubview:(TopViewController object).view];
    

Надеюсь, это поможет.