自定义UIWindows在iOS 8中无法正确旋转 [英] Custom UIWindows do not rotate correctly in iOS 8

查看:130
本文介绍了自定义UIWindows在iOS 8中无法正确旋转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使您的应用程序进入横向模式并执行以下代码:

UIWindow *toastWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
toastWindow.hidden = NO;
toastWindow.backgroundColor = [[UIColor cyanColor] colorWithAlphaComponent:0.5f];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [toastWindow removeFromSuperview];
});

在iOS 7中,您将在整个屏幕上方看到一个透明的蓝色覆盖层,该覆盖层会在5秒钟后消失.在iOS 8中,您将获得一个透明的蓝色覆盖层,覆盖屏幕的一半以上

这显然与Apple在iOS 8中所做的更改有关,在该更改中,屏幕坐标现在是面向界面的,而不是面向设备的,但是以真正的Apple方式,它们似乎在横向模式和旋转方面留下了许多错误. /p>

我可以通过检查设备方向是否为横向并翻转主屏幕边界的宽度和高度来修复"此问题,但这似乎是一个可怕的骇客,它将在Apple再次更改iOS 9中的所有内容时打破. /p>

CGRect frame = [[UIScreen mainScreen] bounds];

if (UIInterfaceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
    frame.size.width = frame.size.height;
    frame.size.height = [[UIScreen mainScreen] bounds].size.width;
}

UIWindow *toastWindow = [[UIWindow alloc] initWithFrame:frame];
toastWindow.hidden = NO;
toastWindow.backgroundColor = [[UIColor cyanColor] colorWithAlphaComponent:0.5f];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [toastWindow removeFromSuperview];
});

有人遇到过这个问题,遇到过更好,更不易碎的解决方案吗?

编辑:我知道我可以只使用UIView并将其添加到键窗口中,但是我想在状态栏上放置一些内容.

解决方案

由于其他原因,您的修复"效果不佳,因为它实际上不会旋转窗口,因此文本和其他子视图以适当的方向显示.换句话说,如果您想使用其他子视图来增强窗口,则它们的方向将不正确.

...

在iOS8中,您需要设置窗口的rootViewController,并且rootViewController需要从"shouldAutoRotate"和"supportedInterfaceOrientations"返回适当的值.关于此的更多信息,请访问: https://devforums.apple.com/message/1050398#1050398

如果您的窗口没有rootViewController,则实际上是在告诉框架窗口永远不要自动旋转.在iOS7中,这没有什么不同,因为该框架始终无法为您完成这项工作.在iOS8中,该框架正在处理旋转,并认为它在限制窗口边界时正在执行您所请求的操作(通过使用nil rootViewController).

尝试一下:

@interface MyRootViewController : UIViewController
@end

@implementation MyRootViewController

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

- (BOOL)shouldAutorotate
{
    return YES;
}

@end

现在,在实例化后将rootViewController添加到您的窗口中:

UIWindow *toastWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
toastWindow.rootViewController = [[MyRootViewController alloc]init];

Get your application into landscape mode and execute the following code:

UIWindow *toastWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
toastWindow.hidden = NO;
toastWindow.backgroundColor = [[UIColor cyanColor] colorWithAlphaComponent:0.5f];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [toastWindow removeFromSuperview];
});

In iOS 7 you will get a transparent blue overlay on top of the entire screen that disappears after 5 seconds. In iOS 8 you will get a transparent blue overlay that covers a little over half the screen

This obviously has something to do with the change Apple did in iOS 8 where the screen coordinates are now interface oriented instead of device oriented but in true Apple fashion they seem to have left a myriad of bugs in landscape mode and rotation.

I can "fix" this by checking if the device orientation is landscape and flip the width and height of the main screen bounds but that seems like a horrible hack that is going to break when Apple changes everything again in iOS 9.

CGRect frame = [[UIScreen mainScreen] bounds];

if (UIInterfaceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
    frame.size.width = frame.size.height;
    frame.size.height = [[UIScreen mainScreen] bounds].size.width;
}

UIWindow *toastWindow = [[UIWindow alloc] initWithFrame:frame];
toastWindow.hidden = NO;
toastWindow.backgroundColor = [[UIColor cyanColor] colorWithAlphaComponent:0.5f];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [toastWindow removeFromSuperview];
});

Has anyone been experiencing this problem and come across a better, less brittle solution?

EDIT: I know I could just use a UIView and add it to the key window but I would like to put something on top of the status bar.

解决方案

Your 'fix' isn't great for another reason, in that it doesn't actually rotate the window so that text and other subviews appear with the appropriate orientation. In other words, if you ever wanted to enhance the window with other subviews, they would be oriented incorrectly.

...

In iOS8, you need to set the rootViewController of your window, and that rootViewController needs to return the appropriate values from 'shouldAutoRotate' and 'supportedInterfaceOrientations'. There is some more about this at: https://devforums.apple.com/message/1050398#1050398

If you don't have a rootViewController for your window, you are effectively telling the framework that the window should never autoRotate. In iOS7 this didn't make a difference, since the framework wasn't doing that work for you anyway. In iOS8, the framework is handling the rotations, and it thinks it is doing what you requested (by having a nil rootViewController) when it restricts the bounds of your window.

Try this:

@interface MyRootViewController : UIViewController
@end

@implementation MyRootViewController

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

- (BOOL)shouldAutorotate
{
    return YES;
}

@end

Now, add that rootViewController to your window after it is instantiated:

UIWindow *toastWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
toastWindow.rootViewController = [[MyRootViewController alloc]init];

这篇关于自定义UIWindows在iOS 8中无法正确旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆