查看所有内容:UIWindow子视图VS UIViewController子视图

问题描述:

为了在所有视图之上制作UIView,例如UIAlertView的行为,我所看到的最佳方式是将其放入应用程序窗口中,即通过添加查看到:查看所有内容:UIWindow子视图VS UIViewController子视图

[[[UIApplication sharedApplication] delegate] window] 

但是,我发现的缺点是它不会自动轮换。为了进行轮换,最好的方法是在当前的AppDelegate上添加视图,但是,通过这样做,它将不再是最重要的。比方说,当视图显示,并有一个modalViewController弹出,模态视图肯定会掩盖视图。

我的问题是,是否有可能将子视图添加到最顶端的窗口支持方向?在这种情况下,我需要两套Nib文件吗? UIAlertView如何结合最*的&方向支持?当我看着UIAlertView.h,我看到实际上有2 UIWindows,一次被称为originalWindow,另一个被称为dimWindow。有没有一个地方可以找到UIAlertView.m的源代码?

只有UIWindow的第一个子视图才会被告知方位变化。 (< iOS8上)

你提的问题非常相似,这一个:

Multiple views in a UIWindow

由于有说,你可以为取向的改变通知注册和处理您的重新布局“顶部”子视图的答案那样。

+1

如何将视图注册到设备以接收旋转事件?它不是视图控制器,所以没有代理功能。我是否必须赶上UIDeviceOrientationDidChangeNotification以更改为相应的方向? – 2012-01-08 02:53:18

这是一个可能的解决方案,我在几个步骤中解释。

  1. 开始与UIViewController继承类,而不是UIView,比方说,类命名为UIViewController
  2. 继承既然你不能注册设备/界面旋转的UIView继承类TopViewController,这是从UIViewController继承TopViewController类有方法响应视图旋转事件。旋转事件现在可以被捕获。
  3. 最后,您可以使用与您在问题中提到的方法相同的方法,将TopViewController视图置于UIWindow的顶部。

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

希望这有助于。

+0

UIViewController的视图属性也不会旋转。不幸。 https://developer.apple.com/library/ios/qa/qa1688/_index.html – khunshan 2014-08-12 13:25:23

我找到的最佳解决方案是创建一个透明的容器视图,将该容器添加到窗口,并将您的警报放入容器中。然后您可以注册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:添加到视图控制器层次根视图控制器上。

+0

我有这个解决方案的问题。我无法在最顶端的容器视图中注册触摸。例如,UIButtons不起作用。 – asendra 2014-12-01 18:52:23

+0

@asendra听起来像你的窗口不是关键窗口,但你可能想发布你自己的问题更多的细节。 – Austin 2014-12-01 18:57:38