iPhone - UIWindow 根据当前方向旋转?

Posted

技术标签:

【中文标题】iPhone - UIWindow 根据当前方向旋转?【英文标题】:iPhone - UIWindow rotating depending on current orientation? 【发布时间】:2011-07-14 17:41:52 【问题描述】:

我正在向我的应用程序添加一个额外的 UIWindow。 我的主窗口可以正确旋转,但我添加的这个附加窗口没有旋转。

根据当前设备方向旋转 UIWindow 的最佳方式是什么?

【问题讨论】:

为什么要添加另一个 UIWindow? “每个 ios 应用程序都需要至少一个窗口——UIWindow 类的一个实例——有些可能包含多个窗口。” (View Programming Guide for iOS) 这并不能回答为什么人们会想要另一个窗口的问题。最常见的用例似乎是视频输出。 迷人。但我读了这个问题。我在回复 Moshe。 @Moshe 创建另一个窗口是尝试将内容放置在 UIPopoverController(它本身创建一个单独的 UIWindow)“上方”时的一种常见技术。从 UIPopoverController 拖放是典型的例子 【参考方案1】:

你需要为 UIWindow 滚动你自己的。

监听UIApplicationDidChangeStatusBarFrameNotification通知,然后设置状态栏变化时的变换。

您可以从-[UIApplication statusBarOrientation] 读取当前方向,并像这样计算变换:

#define DegreesToRadians(degrees) (degrees * M_PI / 180)

- (CGAffineTransform)transformForOrientation:(UIInterfaceOrientation)orientation 

    switch (orientation) 

        case UIInterfaceOrientationLandscapeLeft:
            return CGAffineTransformMakeRotation(-DegreesToRadians(90));

        case UIInterfaceOrientationLandscapeRight:
            return CGAffineTransformMakeRotation(DegreesToRadians(90));

        case UIInterfaceOrientationPortraitUpsideDown:
            return CGAffineTransformMakeRotation(DegreesToRadians(180));

        case UIInterfaceOrientationPortrait:
        default:
            return CGAffineTransformMakeRotation(DegreesToRadians(0));
    


- (void)statusBarDidChangeFrame:(NSNotification *)notification 

    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];

    [self setTransform:[self transformForOrientation:orientation]];


根据您的窗口大小,您可能还需要更新框架。

【讨论】:

@morten-fast 感谢您的提示。但我不知道如何处理轮换的协调系统......x变成ywidth变成height?还是没有? 好的。我做了一些研究,似乎应用程序的主要UIWindow 处理方向变化而不旋转......所以应该有其他方法???有人吗? @oleynikd 在 iOS8 及更高版本上,如果您将 Windows rootViewController 设置为它正在呈现的 UIViewController,它将为您处理旋转(尽管我遇到了一些错误 - 特别是在我的启动应用程序的视图控制器,如果我弹出键盘)【参考方案2】:

只需创建一个带有自己的UIViewUIViewController,将其作为rootViewController 分配给您的窗口,并将所有进一步的用户界面添加到控制器的视图(而不是直接添加到窗口),控制器将处理所有轮换为您服务:

UIApplication * app = [UIApplication sharedApplication];
UIWindow * appWindow = app.delegate.window;

UIWindow * newWindow = [[UIWindow alloc] initWithFrame:appWindow.frame];
UIView * newView = [[UIView alloc] initWithFrame:appWindow.frame];
UIViewController * viewctrl = [[UIViewController alloc] init];

viewctrl.view = newView;
newWindow.rootViewController = viewctrl;

// Now add all your UI elements to newView, not newWindow.
// viewctrl takes care of all device rotations for you.

[newWindow makeKeyAndVisible];
// Or just newWindow.hidden = NO if it shall not become key

当然,同样的设置也可以在界面生成器中创建而无需一行代码(除了在显示窗口之前将帧大小设置为填满整个屏幕)。

【讨论】:

只是好奇,但你为什么说要将所有子视图添加到 newView 而不是 newWindow? @CoDEFRo 因为旋转是由 ViewController (viewctrl) 执行的,而这个 ViewController 只旋转它控制的视图(即newView),然后它将递归地旋转它的所有子视图。如果您将它们直接添加到newWindow,那么您的视图不会被 ViewController 旋转,您将不得不再次手动旋转它们(当您旋转设备时,UIWindow 不会旋转任何视图,它不会)甚至不旋转)。【参考方案3】:

您需要设置新窗口的rootViewController。然后窗口的子视图将正确旋转。

myNewWindow!.rootViewController = self

然后您可以在旋转方法中更改帧。

例如(在 ios8 中快速)

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) customAlertView.frame = UIScreen.mainScreen().bounds

【讨论】:

【参考方案4】:

我不知道你对窗口做了什么。但根控制器需要以 YES 响应 shouldAutorotate。

【讨论】:

谢谢,但该方法仅适用于 UIVievController,我正在尝试旋转 UIWindow【参考方案5】:

您可以为您的 UIWindow 设置 rootController。例如:

fileprivate(set) var bottonOverlayWindow = UIWindow()

self.bottonOverlayWindow.rootViewController = self; 

// 'self' 将是您在其上添加 UIWindow 视图的 ViewController。所以每当你 ViewController 改变方向时,你的窗口视图也会改变它的方向。

如果您遇到任何问题,请告诉我。

【讨论】:

以上是关于iPhone - UIWindow 根据当前方向旋转?的主要内容,如果未能解决你的问题,请参考以下文章

一个视图控制器ios的横向方向

应用程序中多个 UIWindow 的最佳实践

iphone在应用启动时获取设备方向

自定义 UIWindow 方向

makeKeyAndVisible 和 makeKeyWindow - iphone 中的 uiwindow

在单独的 UIWindow 中锁定状态栏方向