Answers:
您可以使用类似的方法UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation)
来确定方向,然后相应地使用尺寸。
但是,在方向更改期间,例如在UIViewController的
- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
使用传入的方向,toInterfaceOrientation
因为UIApplication的statusBarOrientation仍会指向旧的方向,因为它尚未更改(因为您位于will
事件处理程序中)。
摘要
有几个与此相关的帖子,但是每个帖子似乎都表明您必须:
[[UIScreen mainScreen] bounds]
尺寸,链接
工作守则
我通常不会走那么远,但是您激起了我的兴趣。以下代码可以解决问题。我在UIApplication上写了一个Category。我添加了类方法来获取currentSize或给定方向的大小,这就是您在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]
。另外,我运行了上面的代码,因此我知道它可以工作并向各个方向报告正确的响应。请注意,我考虑了状态栏。有趣的是,我必须减去状态栏的高度和宽度的最小值。
希望这可以帮助。:D
其他想法
您可以通过查看UIWindow的rootViewController
属性来获取尺寸。我过去已经看过了,它在纵向和横向上都报告了相同的尺寸,只是报告了旋转变换:
(gdb) po [[[[[UIApplication sharedApplication] keyWindow] rootViewController]视图]
<UILayoutContainerView:0xf7296f0; 帧=(0 0; 320480); 变换= [0,-1,1,0,0,0]; 自动调整大小= W + H; 层= <CALayer:0xf729b80 >>
(gdb) po [[[[[UIApplication sharedApplication] keyWindow] rootViewController]视图]
<UILayoutContainerView:0xf7296f0; 帧=(0 0; 320480); 自动调整大小= W + H; 层= <CALayer:0xf729b80 >>
不确定应用程序的工作方式,但是如果您不使用某种导航控制器,则可以在主视图下有一个UIView,其父级的最大高度/宽度和父级的增大/缩小。然后,您可以这样做:[[[[[[[UIApplication sharedApplication] keyWindow] rootViewController] view] subviews] objectAtIndex:0] frame]
。一方面看起来很激烈,但是您明白了。
但是...在摘要下执行上述3个步骤仍然更好。开始弄乱UIWindows,您会发现奇怪的东西,例如显示UIAlertView将更改UIApplication的键窗口,使其指向该UIAlertView创建的新UIWindow。谁知道?我发现了一个依赖keyWindow的错误并发现它像那样改变后才做了!
applicationFrame
代替bounds
(在UIScreen上),则不必减去状态栏的高度。
mainScreen().bounds.size
已从iOS 8开始依赖方向
这是我的解决方案代码!此方法可以添加到NSObject类的Categroy中,或者您可以定义Top自定义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之后,正如UIScreen的bounds属性的Apple Document所述:
讨论区
在当前坐标空间中指定了该矩形,该矩形考虑了对设备有效的任何接口旋转。因此,当设备在纵向和横向之间旋转时,此属性的值可能会更改。
因此,出于兼容性考虑,我们应该检测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]。绑定在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
}
这些作为我的项目中的标准功能包括在内:
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;
}