我有一个iPad应用程序。在横向取向的UIViewController
认为实际宽度= 1024px
和高度= 768 - 20(的状态栏。) - 44(的导航栏)= 704px
。
所以,我想获得这个[1024 x 704]
大小和我使用self.view.bounds
它。它返回[748 x 1024]
,这是不对的!但是,当我旋转屏幕的两倍(电流 - >肖像 - >电流),视图的边界是正确的 - [1024 x 704]
。
有一种观点初始化是这样的:
- (void)loadView {
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view.backgroundColor = [UIColor lightGrayColor];
}
和范围都得到这样的:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"bounds = %@", NSStringFromCGRect(self.view.bounds));
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
NSLog(@"bounds = %@", NSStringFromCGRect(self.view.bounds));
}
所以,问题是..我怎样才能得到正确的观点在一开始绑定?
按照一些其他的答案,你所看到的问题是,因为旋转发生之前viewDidLoad
被调用。因为iPad总是在纵向模式初始化,如果你在viewDidLoad
大小值,它们将永远是画像的大小 - 这是无论你配置的任何方位。
要获得定向/旋转发生后的尺寸,拿在viewDidAppear
大小值。
我不是特别理解为什么iOS不处理这更好的 - 特别是考虑到在项目设置中定义的方向,并且,在Xcode界面生成器。但是,我敢肯定有一个很好的理由;-)。
你UIViewController
子类应该覆盖的方法viewWillLayoutSubviews
,see also here。
当这个方法被调用时,的viewController的view
有其正确的大小,并可以进行任何必要的调整,之前的布局传过来的子视图子视图。
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
NSLog("bounds = \(self.view.bounds)")
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
NSLog(@"bounds = %@", NSStringFromCGRect(self.view.bounds));
}
当一个视图边界改变,视图调整其子视图的位置。您的视图控制器可以重写此方法来更改视图勾画出它的子视图之前。此方法的默认实现不执行任何操作。
当你从强调的部分看,这种方法称为每次视图控制器的视图改变大小,以及当视图第一次出现。这使您可以正确地响应旋转和其他边界改变事件
在其他的答案提出了几种方法效果不好,或有严重的缺点。不幸的是,这包括所选择的答案。我劝你避免这些方法。我会通过他们去讨论,你不应该使用它们的原因。请不要。
viewDidLoad
和viewWillAppear
- 在这些调用view
还没有最终的大小。你得到的大小将永远只能是纯偶然正确的,从而误导你。viewDidAppear
- 这是为时已晚。您的观点是已经在屏幕上对用户可见。这里制作的变化会引起明显的变化/突发性故障,并期待业余。再次,请 - 为您着想,为我的缘故,大家的缘故:不这样做!你比这更好的等等都是你的用户。UIScreen.mainScreen.bounds.size
- 这是非常低的水平。你实施UIViewController
及其视图的大小取决于它嵌套在(导航,制表符,寻呼,任何定制控制器,等等),该装置是如何旋转,并且潜在地,如何在屏幕已被划分为所述控制器对于多任务处理。所以,虽然你也许能够弥补所有这些和计算你的观点的最终大小,你会复杂和脆弱的代码,如果苹果决定更改这些指标可以轻松突破而告终。 UIViewController
会做这一切为你,如果你只是覆盖viewWillLayoutSubviews
。除了没有提供正确的信息,这些问题的方法不会帮你自动旋转或其他事件,导致视图控制器的视图改变大小,如多任务手势。这是你真正想要顺利处理的东西。
所以请:是冠军。做正确的方式。使用viewWillLayoutSubviews
。你的实现将被调用为各种规模的变化,你的用户,未来的自己,团队成员和我将庆祝你。好样的!
当viewWillLayoutSubviews
被调用时,在您的层次结构中的唯一视图,将被调整到它的最终尺寸为viewController.view
。白送因为这是在方法的名称。它告诉你view…
(您的视图控制器的根view
)…WillLayout…
(真的快了,但它没有发生过)…Subviews
(根视图下,一切都在它的层次其他人)。
因此,子视图布局还没有发生。在根目录下每个孩子都还没有一个有效的最终大小。您从子视图查询的任何大小的信息将在最好的完全错误的。
更有可能的是,更糟极大,这将是误导正确的。
这恰好是你所期望的,在这个大小和方向,或由于你的故事板设置需要因违约。不过,这只是偶然,是不是你可以依靠不同的器件尺寸或方向。
如果你需要在一个特定的子视图改变大小被告知,并且知道它确切的最终大小,你通常应该重写特定layoutSubviews
子类的UIView
方法。
我一直使用:
CGSize sizeOfScreen = [[UIScreen mainScreen] bounds].size;
得到屏幕的大小,以及:
CGSize sizeOfView = self.view.bounds.size;
得到view
的大小。我刚才测试了viewDidLoad中和它返回:
2012-07-17 10:25:46.562 Project[3904:15203] bounds = {768, 1004}
这是正确的,因为CGSize被定义为{宽度,高度}。
这是我在过去的项目中找到:self.view的框架将viewDidLoad中后进行调整,根据如果屏幕上有导航栏等。
因此,也许你想使用viewDidLoad中(也许在viewWillAppear中或viewDidAppear)后的值或者通过的。减去条的高度手动调节。
我就遇到了这个问题,并发现得到的边界在viewDidAppear
我需要工作。