为什么我必须在 viewDidLoad 中手动设置视图的框架?
我在 UITabBarController 内有一个非常基本的 UINavigationController 设置。我想以编程方式布局该导航控制器的 rootViewController 的视图,但是当我查看 viewDidLoad 内的 self.view.frame 时,我得到了这个(例如,在横向中):
1. view frame: {{20, 0}, {748, 1024}} // looks like an odd portrait mode
然后我自动旋转然后,
2. view frame: {{0, 0}, {768, 911}}
当我返回到横向时,框架现在是这样的:
3. view frame: {{0, 0}, {1024, 655}}
进一步的自动旋转事件将在框架值 #2 和 #2 之间翻转。 #3。
为了解决 #1 的怪异问题,我目前正在 viewDidLoad 中执行此操作:
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
self.view.frame = CGRectMake(0, 0, 768, 911);
} else {
self.view.frame = CGRectMake(0, 0, 1024, 655);
}
我觉得我显然在这里遗漏了一些东西。当视图自动旋转回相同方向时,为什么视图的默认框架与框架不匹配?视图框架是否未设置为初始方向?非常困惑......
我应该提到的是,以上所有内容,包括我的笨拙黑客,都没有在视觉上改变任何东西。我进行黑客攻击的原因是,当我将子视图布局到此视图中时,它们将基于我期望的位置,即导航栏下方的左上角。
我做错了什么?
更新:关闭视图上的所有自动调整大小的内容会将结果 #1 更改为:
view frame: {{0, 0}, {748, 1024}}
这看起来有点接近,但仍然不匹配 #3。
I have a pretty basic setup with a UINavigationController inside a UITabBarController. I'm wanting to programmatically layout the view of the rootViewController of that navcontroller, but when I look at self.view.frame inside viewDidLoad, I get this (in landscape, for example):
1. view frame: {{20, 0}, {748, 1024}} // looks like an odd portrait mode
Then I autorotate to Portrait, and I get this:
2. view frame: {{0, 0}, {768, 911}}
Then when I go back to Landscape, the frame is now this:
3. view frame: {{0, 0}, {1024, 655}}
And further autorotation events will flip-flop between frame values #2 & #3.
To get around the weirdness of #1, I'm currently doing this in viewDidLoad:
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
self.view.frame = CGRectMake(0, 0, 768, 911);
} else {
self.view.frame = CGRectMake(0, 0, 1024, 655);
}
I feel like I'm obviously missing something here. Why would the default frame of the view not match the frame when it autorotates back to the same orientation? Does the view frame not get set to the initial orientation? Very confused...
I should mention that none of the above, including my kludgy hack, changes anything visually. The reason I have the hack is so that when I layout my subviews into this view, they'll be based off of where I expect them to be, which is the top left corner just under the navigation bar.
What am I doing wrong?
UPDATE: turning off all the autosizing stuff on the view changes result #1 to be:
view frame: {{0, 0}, {748, 1024}}
That seems a tiny bit closer, but still not matching #3.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不保证 viewDidLoad 中的框架与最终显示视图时的框架相同。 UIKit 在显示视图控制器视图之前根据将要出现的上下文来调整它的框架。大小是根据界面方向和任何可见导航栏、选项卡栏、工具栏或状态栏(其本身的高度可以更改,例如当您正在打电话时)的尺寸来确定的。
它有助于理解加载和显示视图控制器的视图时会发生什么:
某些东西第一次访问视图控制器的
view
属性。这可能发生在您自己的代码中,或者发生在 UIKit 中,以响应用户操作(例如选择选项卡)。UIKit 通过调用
loadView
(如果已定义)来延迟加载视图控制器的视图,或者通过从initWithNibName:bundle:
中指定的 NIB 加载视图。如果两者都不存在,UIKit 只会加载一个空视图。一旦视图及其子视图完全加载,UIKit 就会调用
viewDidLoad
。 此时,视图的框架将是在 NIB 或loadView
中设置的任何内容。需要 UIKit 来显示您的视图控制器的视图。同样,这可能是用户操作,例如点击选项卡,也可能是代码中的显式方法调用,例如
pushViewController:animated:
或presentModalViewController:animated:
。UIKit 根据将呈现视图的上下文来调整
UIKit 调用
viewWillAppear:
。 框架现在应该是要显示的尺寸。 (?)编辑:这可能不再正确。请参阅下面的评论。UIKit 显示视图,带或不带动画。
UIKit 调用
viewDidAppear:
。正如您所看到的,如果您需要在呈现视图框架之前了解视图框架的大小,
viewWillAppear:
是您唯一的机会。请记住,在视图出现后,此尺寸可能会因各种原因而发生变化,包括旋转事件或状态栏高度的变化。因此,为每个子视图提供适当的 autoresizingMask 非常重要,以确保布局可以根据边界的任何变化正确调整自身。如果您希望手动构建视图层次结构,建议在 loadView 中执行此操作。由于您自己在此方法中构造视图,因此您可以将其框架初始化为您想要的任何内容。您选择的大小并不重要,因为 UIKit 可能会根据您的情况更改它。只需确保正确设置 autoresizingMasks 即可。
The frame is not guaranteed to be the same in viewDidLoad as it will be when the view is eventually displayed. UIKit adjusts the frame of your view controller's view prior to displaying it, based on the context in which will appear. The size is determined based on interface orientation and the dimensions of any visible navigation bar, tab bar, toolbar, or status bar (which itself has a height that can change, e.g. when you're on a phone call).
It helps to understand what happens when a view controller's view is loaded and displayed:
Something accesses your view controller's
view
property for the first time. This may occur in your own code, or in UIKit in response to a user action like selecting a tab.UIKit lazy-loads your view controller's view by calling
loadView
if it's defined, or by loading the view from the NIB that was specified ininitWithNibName:bundle:
. If neither exists, UIKit just loads an empty view.UIKit calls
viewDidLoad
once the view and its subviews have been fully loaded. At this point the view's frame will be whatever it was set to in the NIB, or inloadView
.Something calls for UIKit to display your view controller's view. Again, this may be a user action like tapping on a tab, or an explicit method call in your code like
pushViewController:animated:
orpresentModalViewController:animated:
.UIKit resizes the view based on the context in which it will be presented, as described above.
UIKit calls
viewWillAppear:
. The frame should now be the size that will be displayed. (?) EDIT: This may no longer be true. See the comments below.UIKit displays the view, with or without animations.
UIKit calls
viewDidAppear:
.As you can see, if you need to know the size of your view's frame before it gets presented,
viewWillAppear:
is your one and only opportunity. Just remember that this size may change after the view appears for various reasons, including rotation events or changes in status bar height. For this reason, it's important to give every subview an appropriate autoresizingMask, to ensure that the layout can adjust itself properly for any change in bounds.If you wish to build your view hierarchy manually, the recommended place to do so is in loadView. Since you construct the view yourself in this method, you can initialize its frame to whatever you'd like. The size you choose doesn't matter much, since UIKit is likely to change it on you anyway. Just make sure you set your autoresizingMasks appropriately.
你的类中会有一个方法
将你的框架放入这个方法中......然后它就会正常工作。
例如:
FRAME.WIDTH >所需宽度
框架高度>所需高度
There will be a method in your class
Put your frame in this method... Then it will work fine.
For example:
FRAME.WIDTH > desired width
FRAME.HEIGHT > desired height