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

Posted

技术标签:

【中文标题】以编程方式创建一个视图,将框架设置为超级视图的框架?【英文标题】:create a view programmatically with frame set to superview's frame? 【发布时间】:2010-11-09 05:46:14 【问题描述】:

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

首先,我想知道如何获取“导航视图”的框架,以便我可以将自定义视图正确放置在上面。 此外,我有时会隐藏导航栏并希望确保正确获取框架信息。 (不带 [[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 的边界。 问题是我无法访问 viewDidLoad 中的超级视图。 我可以看到在 viewWillAppear 中正确设置了 superview,但在 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 访问超级视图,因此我无法像之前在 viewDidLoad 中那样布局视图。这似乎很不方便,而且不必要地复杂。 请问有什么建议吗?

【问题讨论】:

你需要在 ios 中读取视图层次结构。 【参考方案1】:

superview 属性为 nil,直到您的视图被添加为某处的子视图。通常,您无法知道 loadView 方法中的超级视图是什么。

您可以按照 Costique 的建议使用自动调整大小的属性。查看the official UIView docs 中的调整子视图大小

您还可以在调用loadView 之后设置框架,例如:

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.

【讨论】:

谢谢,我想我可以做 self.view.frame = self.view.superview.bounds;在我看来DidLoad()。但我注意到我在 loadView 中创建了我的视图,但我实际上并没有做任何事情来通过 addSubview 或任何东西将它添加到 superview 中。所以代码没有做任何事情。奇怪的是,我能够看到该视图而无需之前将其添加到父视图。如何将我的视图(在 loadView 中创建)添加到父视图? 抱歉,我在阅读自己的代码时搞砸了。我猜它是在做 UINavigationController 的 initWithRootViewController 时添加的【参考方案2】:

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

myView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;

【讨论】:

啊,谢谢,我想它会正常工作的。但我有一个滚动视图作为 myView 之一。我想将 autoresizingMask 设置为滚动视图不起作用? 为什么不呢? UIScrollView 只是一个专门的 UIView,它操纵其边界原点进行滚动。唯一不同的是我用 [UIScreen mainScreen].applicationFrame 而不是 CGRectZero 初始化 UIViews,但我认为这根本不重要。 我已经尝试了你的建议。但在我的 viewDidLoad() 中,[self.view bounds](布局子视图)返回(0,0,0,0)。我在什么地方搞砸了吗?你在 viewDidLoad 中得到了正确的 [self.view bounds] 吗? 如果我没记错的话,viewDidLoad 是在视图添加到导航控制器的视图层次结构之前发送的,在 loadView 之后立即发送。它应该在发送 viewDidAppear: 时添加到超级视图中。因此,如果您需要计算一些几何图形,Apple 建议您将初始视图框架设置为 [UIScreen mainScreen].applicationFrame。顺便说一句,如果你设置了 view 属性,你不应该发送 [super loadView]。

以上是关于以编程方式创建一个视图,将框架设置为超级视图的框架?的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式从超级视图中删除视图后更新约束/框架(自动布局)

即使启用了自动布局,我能否以编程方式设置特定视图的框架?

为啥我以编程方式创建的视图会忽略其约束?

如何以编程方式设置子视图的框架以使其适合其父视图?

基于在 Storyboard 中使用自动布局创建的另一个视图,以编程方式使用框架创建视图

获取以编程方式创建的子视图的框架