我正在尝试以编程方式确定我的应用程序的当前高度和宽度。我使用以下代码:
CGRect screenRect = [[UIScreen mainScreen] bounds];
但是这会产生一个宽度为320和高度为480的结果,无论设备是否处于纵向或横向方向。我该如何确定我的主屏幕的当前宽度和高度(即取决于设备方向)?
我正在尝试以编程方式确定我的应用程序的当前高度和宽度。我使用以下代码:
CGRect screenRect = [[UIScreen mainScreen] bounds];
但是这会产生一个宽度为320和高度为480的结果,无论设备是否处于纵向或横向方向。我该如何确定我的主屏幕的当前宽度和高度(即取决于设备方向)?
您可以使用类似 UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation)
的方法来确定方向,然后相应地使用尺寸。
但是,在 UIViewController 中进行方向更改时...
- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
在toInterfaceOrientation
中使用传递的方向,因为UIApplication的statusBarOrientation仍将指向旧方向,因为它尚未更改(因为您在will
事件处理程序内)。
摘要
有几篇相关的帖子,但每篇都似乎表明您必须:
[[UIScreen mainScreen] bounds]
以获取尺寸,链接
工作代码
我通常不这样做,但你引起了我的兴趣。下面的代码应该可以胜任。我写了一个UIApplication类别。我添加了用于获取当前大小或给定方向中的大小的类方法,这是您在UIViewController的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]
。同时,我运行了以上代码,所以我知道它可以在所有方向上正确地报告出正确的响应。请注意,我考虑了状态栏。有趣的是,我必须减去状态栏高度和宽度中的最小值。rootViewController
属性来获取尺寸。我过去曾经研究过这个问题,它同样会在纵向和横向时报告相同的尺寸,但是它会报告旋转变换:[[[[[[[UIApplication sharedApplication] keyWindow] rootViewController] view] subviews] objectAtIndex:0] frame]
。这看起来有一行非常强大,但你能理解它的意思。这是我的解决方案代码!这种方法可以添加到NSObject类的类别中,或者您可以定义一个顶级自定义UIViewController类,并让所有其他的UIViewControllers都继承它。
-(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之后,如Apple Document of UIScreen's bounds property所述:
讨论
此矩形在当前坐标空间中指定,考虑到设备上生效的任何接口旋转。因此,当设备在纵向和横向方向之间旋转时,此属性的值可能会更改。
因此,考虑到兼容性,我们应检测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 ;
}
这里有一个方便的宏:
#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
}];
}
这个方法替代了已弃用的动画方法,该方法没有提供有关大小的信息:
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration
iOS 8 及以上版本,屏幕边界的返回值现在已根据当前屏幕方向进行了修正。这意味着在 iPad 横屏模式下,[UIScreen mainScreen].bounds 在 iOS 7 及以下版本上返回值是 768,在 iOS 8 上则为 1024。
以下代码可在所有发布的 iOS 版本上正确返回屏幕高度和宽度。
-(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
以下是一种用Swift获取方向相关屏幕尺寸的简便方法:
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
}
这些是我项目中的标准函数:
(EZSwiftExtensions是一个包含常用Swift扩展的开源库)使用 -> setNeedsDisplay() 方法来调整你想要改变大小的视图。
以下是一些在Swift中提供的答案改进:
let interfaceOrientation = UIApplication.shared.statusBarOrientation // (< iOS 13)
let screenSize = UIScreen.main.bounds.size
let screenWidth = interfaceOrientation.isPortrait ? screenSize.width : screenSize.height
let screenHeight = interfaceOrientation.isPortrait ? screenSize.height : screenSize.width
applicationFrame
而不是bounds
(在UIScreen上),则无需减去状态栏高度。 - aopsfan9.0.2
。在 iPhone 5s 上,横屏和竖屏模式下,我得到了相同的尺寸(568.0, 300.0)
。 - AechoLiumainScreen().bounds.size
已成为方向相关的。 - Gerald