以编程方式创建一个视图,并将其框架设置为父视图的框架?

10

我有一个基于导航的应用程序,我将我的自定义视图放置在导航视图中。

首先,我想知道如何获取“导航视图”的框架,以便我可以正确地放置我的自定义视图。
此外,有时我会隐藏导航栏,并希望确保正确获取框架信息。(不使用[[UIScreen mainScreen] bounds])

其次,在一般情况下,我如何访问父视图的框架,以便我可以相应地放置一个视图?
我尝试了以下方法,但没有成功。

-(void) loadView {
[super loadView];
UIView* myView = [[UIView alloc] initWithFrame: CGRectZero];
self.view = myView;
self.view.frame = self.view.superview.frame;
[myView release];
}

或者在layoutSubviews中设置框架,但是注意到layoutSubviews没有被调用。我猜这是因为在这个特定的视图中没有任何子视图?

谢谢

-编辑-

根据给出的答案,我现在知道我需要将view.frame设置为superview的bounds。
问题是我无法在viewDidLoad中访问superview。
我可以看到superview在viewWillAppear中被正确设置,但在viewDidLoad中没有。

我发现viewDidLoad在各种时候被调用,例如通过pushViewController推送或访问self.view
我有以下代码,并且当nil == controller.view.superview时,viewDidLoad会被调用。

if (nil == controller.view.superview) {
    CGRect frame = scrollView.frame;
    frame.origin.x = frame.size.width * page;
    frame.origin.y = 0;
    controller.view.frame = frame;
    [scrollView addSubview:controller.view];
}

因为我无法从viewDidLoad中访问superview,所以我无法像之前在viewDidLoad中布局视图那样做。这似乎很不方便并且过于复杂。
请问有什么建议吗?


你需要在iOS中阅读视图层次结构。 - Tirth
2个回答

10
superview属性在将你的视图添加为子视图之前为nil。通常情况下,你无法知道loadView方法中superview会是什么。
你可以使用自动调整大小的属性,如Costique所建议的。请查看官方UIView文档中的调整子视图
你也可以在调用loadView后设置frame,例如以下示例代码:
MyViewController *myController = [[MyViewController alloc] init];
myController.view.frame = window.bounds;
[window addSubview:myController.view];

顺便说一下,通常更安全的做法是使用父视图的 bounds 属性作为子视图的框架。这是因为父视图的边界与子视图的框架在同一坐标系中,但父视图的框架可能不同。例如:

UIView *parentView = /* set up this view */;
UIView *subView = /* set up subview */;
[parentView addSubview:subView];
parentView.frame = CGRectMake(30, 50, 10, 10);
subView.frame = subView.superview.frame;  // BAD!!!
// Right now subView's offset is (30, 50) within parentView.
subView.frame = subView.superview.bounds;  // Better.
// Now subView is in the same position/size as its parent.

谢谢,我原以为可以在viewDidLoad()中使用self.view.frame = self.view.superview.bounds;,但我注意到我是在loadView中创建我的视图,但我并没有通过addSubview或其他方式将它添加到superview中。所以这段代码什么也没做。奇怪的是,以前我能看到视图而不将其添加到父视图中。我该如何将我创建在loadView中的视图添加到父视图中? - eugene
抱歉,我读错了自己的代码。我猜这是在 UINavigationController 的 initWithRootViewController 中添加的。 - eugene

7

只需设置自动调整大小的掩码,导航控制器将完成其余操作:

myView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;

啊,谢谢。我猜它应该可以正常工作。但是我的一个视图中有一个滚动视图。将autoresizingMask设置为滚动视图不起作用,我想是吧? - eugene
为什么不呢?UIScrollView只是一个专门用于滚动的UIView,它通过操作其边界原点来实现滚动。我唯一不同的做法就是使用[UIScreen mainScreen].applicationFrame来初始化UIView,而不是CGRectZero,但我认为这并不重要。 - Costique
我尝试了你的建议。但是在我的viewDidLoad()方法中,[self.view bounds](用于布局子视图)返回(0,0,0,0)。我做错了什么吗?你在viewDidLoad()方法中得到了正确的[self.view bounds]吗? - eugene
1
如果我没记错的话,viewDidLoad 在视图添加到导航控制器的视图层次结构之前发送,紧接着是 loadView。在发送 viewDidAppear: 之前,它应该被添加到 superview 中。因此,如果您需要计算一些几何参数,Apple 建议您将初始视图框架设置为 [UIScreen mainScreen].applicationFrame。顺便说一下,如果您设置了视图属性,就不应该发送 [super loadView]。 - Costique

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接