UIWindow方向问题(两个UIWindows和横向模式)



我知道这看起来是一个很大的问题,但事实并非如此,所以不要害怕阅读它。主要是我在解释东西是如何工作的。

我的应用程序中有两个UIWindow。第一个是主窗口,默认情况下由应用程序创建。第二个名为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;
}

我通过[[[UIApplication sharedApplication] delegate] performSelector....]呼叫presentActivityOnModalWindow。我知道这不是最好的做法,但效果很好。关于解雇,我使用NSNotificationCenter发布解雇通知。modalWindow上的视图控制器仅支持人像模式。它在shouldAutorotate返回YES,在supportedInterfaceOrientations返回UIInterfaceOrientationMaskPortrait

好的,解释了很多,但现在我们来解决问题。当我旋转到横向模式时,弹出模式窗口,关闭模式窗口,然后旋转回纵向模式,我的主窗口仍处于横向模式,一切看起来都是灾难性的。

我尝试在windowmodalWindow中添加一个观察器,并记录framebounds中的更改,结果如下:

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似乎无法恢复到正常帧如何解决此问题如果我需要提供更多细节,请随时询问。

系统将只处理keyWindow的旋转。如果您有其他窗口,则必须自己处理旋转。

我还认为模态控制器是可行的。但是,如果你真的想处理旋转,看看其他"自定义窗口"库是如何处理旋转的。警报视图就是一个很好的例子:

https://github.com/search?o=desc&q=uialertview&s=星形&type=存储库&utf8=✓

Apple不鼓励以这种方式使用windows。可能最好使用模式显示的UIViewController来代替

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

使用从UIViewController实例以模式呈现UIViewController

[self presentViewController:<#(UIViewController *)#> animated:<#(BOOL)#> completion:<#^(void)completion#>]

您正在创建两个窗口,Apple建议不要这样做。一个应用程序应该有和显示设备一样多的窗口。(SEE UIWindow参考)

我建议使用两个视图,并根据方向将所有内容"绘制"到这些视图上。然后在显示另一个视图时,将其中一个视图隐藏起来。

或者,您可以只使用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个屏幕上显示的数据差异的信息。干杯。]

最新更新