【问题标题】:UIWindow orientation issues (two UIWindows and landscape mode)UIWindow 方向问题(两个 UIWindows 和横向模式)
【发布时间】:2015-02-20 09:00:20
【问题描述】:

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

我的应用中有两个UIWindows。第一个是应用程序默认创建的主窗口。第二个称为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,此时我会关闭横向视图控制器。

现在让我们解释第二个窗口是如何发挥作用的。在横向模式下,有一个动作(只需按下按钮)会在第二个窗口(@98​​7654327@)上显示一个新的视图控制器。好的,让我们解释一下。

应用程序委托有两个方法,如下所示:

- (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 似乎没有回到正常帧。 如何解决这个问题?如果我需要提供更多详细信息,请随时询问。

【问题讨论】:

    标签: ios objective-c uiviewcontroller ios8 uiwindow


    【解决方案1】:

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

    我也认为模态控制器是要走的路。但是,如果您真的想处理旋转,请查看其他“自定义窗口”库如何处理旋转。警报视图就是一个很好的例子:

    https://github.com/search?o=desc&q=uialertview&s=stars&type=Repositories&utf8=

    【讨论】:

      【解决方案2】:

      Apple 不鼓励以这种方式使用 Windows。最好使用模态显示的UIViewController 而不是您的

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

      以模态方式呈现UIViewController 是从UIViewController 实例使用

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

      【讨论】:

        【解决方案3】:

        您正在创建 2 个窗口,Apple 建议不要这样做。一个应用确实应该有与显示设备一样多的窗口。(SEE UIWindow reference)

        我建议使用 2 个视图并根据方向将所有内容“绘制”到这些视图上。然后在显示另一个视图时隐藏一个视图。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多