iphone - 查看一切之上 : UIWindow subview VS UIViewController subview

标签 iphone xcode uiview uialertview uiwindow

为了在所有 View 之上创建一个UIView,就像UIAlertView的行为一样,我看到的最好的方法是将它放在应用程序窗口中,这是通过将 View 添加到:

[[[UIApplication sharedApplication] delegate] window]

但是,我发现的缺点是它不会自动轮换。为了让它轮流,最好的方法是在当前 AppDelegate window.navigationController/rootViewController 上添加 View ,但是,这样做不会不再掌控一切。假设当 View 正在显示并且有一个 modalViewController 弹出窗口时,模态视图肯定会覆盖 View 。

我的问题是,是否可以将 subview 添加到最顶部的窗口支持方向?在这种情况下我需要两套 Nib 文件吗? UIAlertView 如何神奇地结合最顶层和方向支持?当我查看 UIAlertView.h 时,我发现实际上有 2 个 UIWindows,一个称为 originalWindow,另一个称为 dimWindow。有没有地方可以找到 UIAlertView.m 的源代码?

最佳答案

我发现的最佳解决方案是创建一个透明的容器 View ,将该容器添加到窗口中,并将警报放置在容器内。然后,您可以注册 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 之上,包括键盘,但窗口管理有点棘手。上述解决方案应该足以满足大多数需求。

简单地将 View Controller 的 View 添加到窗口的问题是,不能保证收到所有旋转和 view[Will|Did][Disa|A]ppear: 消息,除非它通过 Root View Controller 上的 addChildViewController: 添加到 View Controller hierarchy

关于iphone - 查看一切之上 : UIWindow subview VS UIViewController subview,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8774495/

相关文章:

iOS - 如何删除以前添加的 UIView 子层

iphone - 模拟 iPhone 5 上的 iOS 应用程序崩溃与分辨率

ios - 一旦异步调用在 swift 中出现,就停止它

ios - 禁用与 UIBarButtonItem 的用户交互

ios - 具有自动布局的 UITableView 滚动时不平滑

ios - 以编程方式添加导航栏按钮...但它不会显示!

xcode - NSOpenPanel在选择文件时崩溃

iphone - 批量插入到 iPhone 上的 sqlite 数据库中

ios - animationControllerForPresentedController 和 animateTransition 之间的自定义过渡动画未知延迟

javascript - 输入类型 radio 在 iPhone 上不工作