如何获得屏幕的方向相关的高度和宽度?

我试图以编程方式确定我的应用程序的当前的高度和宽度。 我使用这个:

CGRect screenRect = [[UIScreen mainScreen] bounds]; 

但是,这会产生宽度为320,高度为480,无论设备是纵向还是横向。 我怎样才能确定我的主屏幕的当前宽度和高度(即取决于设备的方向)?

您可以使用像UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation)来确定方向,然后相应地使用尺寸。

然而,在像UIViewController的方向变化

 - (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 

由于UIApplication的statusBarOrientation仍然指向旧的方向,因为它还没有改变(因为你在一个will事件处理程序中),所以使用传递toInterfaceOrientation的方向。

概要

有几个相关的职位,但他们每个人似乎表明,你必须:

  1. 看看[[UIScreen mainScreen] bounds]来获取尺寸,
  2. 检查你在什么方向,和
  3. 帐户状态栏高度(如果显示)

链接

  • iPhone:获取当前视图尺寸或屏幕尺寸
  • iPhone / iPad:如何以编程方式获取屏幕宽度?
  • 目标C – 如何获得当前的屏幕分辨率?
  • iPhone或iPad重新定位后的“框架/窗口大小”不正确
  • iPhone开发SDK – 获取屏幕宽度

工作代码

我通常不会走这么远,但你激起了我的兴趣。 下面的代码应该做的伎俩。 我在UIApplication上写了一个类别。 我添加了获取currentSize或size的方法,这就是你要在UIViewController的willRotateToInterfaceOrientation:duration:调用的willRotateToInterfaceOrientation:duration:

 @interface UIApplication (AppDimensions) +(CGSize) currentSize; +(CGSize) sizeInOrientation:(UIInterfaceOrientation)orientation; @end @implementation UIApplication (AppDimensions) +(CGSize) currentSize { return [UIApplication sizeInOrientation:[UIApplication sharedApplication].statusBarOrientation]; } +(CGSize) sizeInOrientation:(UIInterfaceOrientation)orientation { CGSize size = [UIScreen mainScreen].bounds.size; UIApplication *application = [UIApplication sharedApplication]; if (UIInterfaceOrientationIsLandscape(orientation)) { size = CGSizeMake(size.height, size.width); } if (application.statusBarHidden == NO) { size.height -= MIN(application.statusBarFrame.size.width, application.statusBarFrame.size.height); } return size; } @end 

使用代码简单调用[UIApplication currentSize] 。 此外,我运行上面的代码,所以我知道它的工作原理,并报告所有方向的正确答案。 请注意,我在因素在状态栏。 有趣的是我不得不减去状态栏的高度和宽度的最小值。

希望这可以帮助。 :d

其他想法

您可以通过查看UIWindow的rootViewController属性来获取维度。 我已经在过去看了这个,它也类似地报告纵向和横向相同的尺寸,除了它报告有一个旋转变换:

(gdb) po [[[[UIApplication sharedApplication] keyWindow] rootViewController] view]

<UILayoutContainerView:0xf7296f0; frame =(0 0; 320 480); transform = [0,-1,1,0,0,0]; autoresize = W + H; 层= <CALayer:0xf729b80 >>

(gdb) po [[[[UIApplication sharedApplication] keyWindow] rootViewController] view]

<UILayoutContainerView:0xf7296f0; frame =(0 0; 320 480); autoresize = W + H; 层= <CALayer:0xf729b80 >>

不知道你的应用程序是如何工作的,但是如果你没有使用某种导航控制器,你可以在你的主视图下面有一个UIView,它的父母的最大高度/宽度和父母的增长/缩小。 然后你可以这样做: [[[[[[[UIApplication sharedApplication] keyWindow] rootViewController] view] subviews] objectAtIndex:0] frame] 。 这看起来非常紧张,但你明白了。

但是…总结下面的3个步骤还是比较好的。 开始搞乱UIWindows,你会发现奇怪的东西,如显示一个UIAlertView将改变UIApplication的关键窗口指向一个新的UIAlertView创build的UIWindow。 谁知道? 我发现一个依赖keyWindow的bug后发现它改变了!

这是我的解决scheme代码!这个方法可以添加到NSObject类的Categroy,或者你可以定义一个Top定制的UIViewController类,让所有其他的UIViewControllerinheritance它。

 -(CGRect)currentScreenBoundsDependOnOrientation { CGRect screenBounds = [UIScreen mainScreen].bounds ; CGFloat width = CGRectGetWidth(screenBounds) ; CGFloat height = CGRectGetHeight(screenBounds) ; UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation; if(UIInterfaceOrientationIsPortrait(interfaceOrientation)){ screenBounds.size = CGSizeMake(width, height); }else if(UIInterfaceOrientationIsLandscape(interfaceOrientation)){ screenBounds.size = CGSizeMake(height, width); } return screenBounds ; } 

请注意 ,在iOS8之后, UIScreen的界限属性的Apple文档说:

讨论

这个矩形是在当前的坐标空间中指定的,它考虑到了设备的任何接口旋转。 因此,当设备在纵向和横向之间旋转时,此属性的值可能会发生变化。

所以为了考虑兼容性,我们应该检测IOS版本,并做如下修改:

 #define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) -(CGRect)currentScreenBoundsDependOnOrientation { CGRect screenBounds = [UIScreen mainScreen].bounds ; if(IsIOS8){ return screenBounds ; } CGFloat width = CGRectGetWidth(screenBounds) ; CGFloat height = CGRectGetHeight(screenBounds) ; UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation; if(UIInterfaceOrientationIsPortrait(interfaceOrientation)){ screenBounds.size = CGSizeMake(width, height); }else if(UIInterfaceOrientationIsLandscape(interfaceOrientation)){ screenBounds.size = CGSizeMake(height, width); } return screenBounds ; } 

这是一个方便的macros:

 #define SCREEN_WIDTH (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height) #define SCREEN_HEIGHT (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width) 

在iOS 8 +中,您应该使用viewWillTransitionToSize:withTransitionCoordinator方法:

 -(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; // You can store size in an instance variable for later currentSize = size; // This is basically an animation block [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { // Get the new orientation if you want UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; // Adjust your views [self.myView setFrame:CGRectMake(0, 0, size.width, size.height)]; } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { // Anything else you need to do at the end }]; } 

这取代了不提供大小信息的弃用animation方法:

 -(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration 

从iOS 8屏幕边界现在返回正确的当前方向。 这意味着横向的一个iPad [UIScreen mainScreen] .bounds会在iOS 7上返回768,在iOS 8上返回1024。

以下内容将返回所有已发布版本的正确高度和宽度。

 -(CGRect)currentScreenBoundsDependOnOrientation { NSString *reqSysVer = @"8.0"; NSString *currSysVer = [[UIDevice currentDevice] systemVersion]; if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending) return [UIScreen mainScreen].bounds; CGRect screenBounds = [UIScreen mainScreen].bounds ; CGFloat width = CGRectGetWidth(screenBounds) ; CGFloat height = CGRectGetHeight(screenBounds) ; UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation; if(UIInterfaceOrientationIsPortrait(interfaceOrientation)){ screenBounds.size = CGSizeMake(width, height); NSLog(@"Portrait Height: %f", screenBounds.size.height); }else if(UIInterfaceOrientationIsLandscape(interfaceOrientation)){ screenBounds.size = CGSizeMake(height, width); NSLog(@"Landscape Height: %f", screenBounds.size.height); } return screenBounds ; } 

如果你想取决于方向的大小,你有一个视图,你可以使用:

 view.bounds.size 

我写了UIScreen类别,适用于所有的iOS版本,所以你可以像这样使用它:
[[UIScreen mainScreen] currentScreenSize]

 @implementation UIScreen (ScreenSize) - (CGSize)currentScreenSize { CGRect screenBounds = [[UIScreen mainScreen] bounds]; CGSize screenSize = screenBounds.size; if ( NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1 ) { UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; if ( UIInterfaceOrientationIsLandscape(interfaceOrientation) ) { screenSize = CGSizeMake(screenSize.height, screenSize.width); } } return screenSize; } @end 

这是一个迅速的方式来获取方向依赖的屏幕尺寸:

 var screenWidth: CGFloat { if UIInterfaceOrientationIsPortrait(screenOrientation) { return UIScreen.mainScreen().bounds.size.width } else { return UIScreen.mainScreen().bounds.size.height } } var screenHeight: CGFloat { if UIInterfaceOrientationIsPortrait(screenOrientation) { return UIScreen.mainScreen().bounds.size.height } else { return UIScreen.mainScreen().bounds.size.width } } var screenOrientation: UIInterfaceOrientation { return UIApplication.sharedApplication().statusBarOrientation } 

这些在我的一个项目中被列为一个标准function:

https://github.com/goktugyil/EZSwiftExtensions

 float msWidth = [[UIScreen mainScreen] bounds].size.width*(IS_RETINA?2.0f:1.0f); float msHeight = [[UIScreen mainScreen] bounds].size.height*(IS_RETINA?2.0f:1.0f); if ( UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ) { os->setWidth(MIN(msWidth, msHeight)); os->setHeight(MAX(msWidth, msHeight)); } else { os->setWidth(MAX(msWidth, msHeight)); os->setHeight(MIN(msWidth, msHeight)); } NSLog(@"screen_w %f", os->getWidth()); NSLog(@"screen_h %f", os->getHeight()); 

但是,在iOS 8.0.2上:

 + (NSUInteger)currentWindowWidth { NSInteger width = 0; UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; CGSize size = [UIScreen mainScreen].bounds.size; // if (UIInterfaceOrientationIsLandscape(orientation)) { // width = size.height; // } else { width = size.width; // } return width; }