嵌入 UIViewController 的子容器的自动布局
Auto layout of a Child Container that embeds a UIViewController
我的主场景显示了一个子 UIViewController
,方法是在其视图中放置一个子容器,并在该子容器中嵌入一个子 UIViewController。我通过按住 ctrl 键从子容器拖动到 storyboard
中的子 UIViewController
,然后选择 "embed" segue。
这让我可以在其他地方封装和重用子 UIViewController
。我认为这是相当标准的。但是我不能让它正确地自动布局。
我做了一个简单的测试用例来证明这一点:
https://github.com/murraycu/ios-example-autolayout-of-child-container-views
它有两个 UIViewControllers
嵌入在选项卡控制器中,因此您可以在它们之间切换。
"Simple" 选项卡显示 SimpleViewController
,其中显示图像和标签,在故事板中可见:
UIImage 或 UILabel 均未指定高度约束,但它们具有等宽(等于父视图)约束以保持宽度简单。
UILabel 显然不是很高,但 UIImage 和 UILabel 的 Content Hugging 优先级略有不同,因此根据自动布局,它们的高度不会模糊。因此,多亏了自动布局,当我在运行时将其文本设置为一些需要更多 space 的文本时,它会占用更多 space,从而使 space 远离其上方的 UIImage。很好 - 这是我想要的行为,如在模拟器中所见:
现在问题来了:"With Child Container" 选项卡显示 WithChildContainerViewController,它显示相同的图像但显示我的 ChildViewController(嵌入在子容器中)而不是 UILabel。嵌入的 ChildViewController 显示 UILabel。它在情节提要中:
但是,自动布局系统现在似乎不知道子容器需要多少 space 才能在我的 ChildViewController 中显示标签中的所有文本。与 "Simple" 选项卡中一样,UIImage 或子容器都没有指定高度约束。现在 XCode 抱怨 "Height is ambiguous for " 容器视图”。在模拟器中看起来像这样:
如果我向子容器添加约束,将其底部限制在父视图的底部,这会有所改善,正如@iphonic 所建议的:https://github.com/murraycu/ios-example-autolayout-of-child-container-views/commit/1d295fe0a6c4502764f8725d3b99adf8dab6b9ae 但高度仍然错误:
如何让自动布局系统知道要做什么?我考虑过实现 UIView 的 intrinsicContentSize,但 UIViewController 不是 UIView。
建议是,以编程方式而不是通过 IB。见下文
_childController=[self.storyboard instantiateViewControllerWithIdentifier:@"ChildController"];
[self addChildViewController:_childController];
[_container addSubview:_childController.view];
[_childController didMoveToParentViewController:self];
_childController.view.frame=_container.bounds;
//add constraints
UIView *subView=_childController.view;
UIView *parent=_container;
subView.translatesAutoresizingMaskIntoConstraints=NO;
NSLayoutConstraint *width =[NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeWidth
relatedBy:0
toItem:parent
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:0];
NSLayoutConstraint *height =[NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeHeight
relatedBy:0
toItem:parent
attribute:NSLayoutAttributeHeight
multiplier:1.0
constant:0];
NSLayoutConstraint *top = [NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:parent
attribute:NSLayoutAttributeTop
multiplier:1.0f
constant:0.f];
NSLayoutConstraint *leading = [NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:parent
attribute:NSLayoutAttributeLeading
multiplier:1.0f
constant:0.f];
[parent addConstraint:width];
[parent addConstraint:height];
[parent addConstraint:top];
[parent addConstraint:leading];
希望对您有所帮助。
干杯。
@iphonic 的代码但使用可视格式语言
_childController = [self.storyboard instantiateViewControllerWithIdentifier: @"ChildController"];
[self addChildViewController: _childController];
[_container addSubview: _childController.view];
[_childController didMoveToParentViewController: self];
//add constraints
NSDictionary *views = @{@"subView": _childController.view,
@"parent": _container};
[parent addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat: @"V:|[subView(==parent)]"
options: 0
metrics: nil
views: views]];
[parent addConstraints: [NSLayoutConstraint
constraintsWithVisualFormat:@"H:|[subView(==parent)]"
options: 0
metrics: nil
views: views]];
我的主场景显示了一个子 UIViewController
,方法是在其视图中放置一个子容器,并在该子容器中嵌入一个子 UIViewController。我通过按住 ctrl 键从子容器拖动到 storyboard
中的子 UIViewController
,然后选择 "embed" segue。
这让我可以在其他地方封装和重用子 UIViewController
。我认为这是相当标准的。但是我不能让它正确地自动布局。
我做了一个简单的测试用例来证明这一点: https://github.com/murraycu/ios-example-autolayout-of-child-container-views
它有两个 UIViewControllers
嵌入在选项卡控制器中,因此您可以在它们之间切换。
"Simple" 选项卡显示 SimpleViewController
,其中显示图像和标签,在故事板中可见:
UIImage 或 UILabel 均未指定高度约束,但它们具有等宽(等于父视图)约束以保持宽度简单。
UILabel 显然不是很高,但 UIImage 和 UILabel 的 Content Hugging 优先级略有不同,因此根据自动布局,它们的高度不会模糊。因此,多亏了自动布局,当我在运行时将其文本设置为一些需要更多 space 的文本时,它会占用更多 space,从而使 space 远离其上方的 UIImage。很好 - 这是我想要的行为,如在模拟器中所见:
现在问题来了:"With Child Container" 选项卡显示 WithChildContainerViewController,它显示相同的图像但显示我的 ChildViewController(嵌入在子容器中)而不是 UILabel。嵌入的 ChildViewController 显示 UILabel。它在情节提要中:
但是,自动布局系统现在似乎不知道子容器需要多少 space 才能在我的 ChildViewController 中显示标签中的所有文本。与 "Simple" 选项卡中一样,UIImage 或子容器都没有指定高度约束。现在 XCode 抱怨 "Height is ambiguous for " 容器视图”。在模拟器中看起来像这样:
如果我向子容器添加约束,将其底部限制在父视图的底部,这会有所改善,正如@iphonic 所建议的:https://github.com/murraycu/ios-example-autolayout-of-child-container-views/commit/1d295fe0a6c4502764f8725d3b99adf8dab6b9ae 但高度仍然错误:
如何让自动布局系统知道要做什么?我考虑过实现 UIView 的 intrinsicContentSize,但 UIViewController 不是 UIView。
建议是,以编程方式而不是通过 IB。见下文
_childController=[self.storyboard instantiateViewControllerWithIdentifier:@"ChildController"];
[self addChildViewController:_childController];
[_container addSubview:_childController.view];
[_childController didMoveToParentViewController:self];
_childController.view.frame=_container.bounds;
//add constraints
UIView *subView=_childController.view;
UIView *parent=_container;
subView.translatesAutoresizingMaskIntoConstraints=NO;
NSLayoutConstraint *width =[NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeWidth
relatedBy:0
toItem:parent
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:0];
NSLayoutConstraint *height =[NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeHeight
relatedBy:0
toItem:parent
attribute:NSLayoutAttributeHeight
multiplier:1.0
constant:0];
NSLayoutConstraint *top = [NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:parent
attribute:NSLayoutAttributeTop
multiplier:1.0f
constant:0.f];
NSLayoutConstraint *leading = [NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:parent
attribute:NSLayoutAttributeLeading
multiplier:1.0f
constant:0.f];
[parent addConstraint:width];
[parent addConstraint:height];
[parent addConstraint:top];
[parent addConstraint:leading];
希望对您有所帮助。
干杯。
@iphonic 的代码但使用可视格式语言
_childController = [self.storyboard instantiateViewControllerWithIdentifier: @"ChildController"];
[self addChildViewController: _childController];
[_container addSubview: _childController.view];
[_childController didMoveToParentViewController: self];
//add constraints
NSDictionary *views = @{@"subView": _childController.view,
@"parent": _container};
[parent addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat: @"V:|[subView(==parent)]"
options: 0
metrics: nil
views: views]];
[parent addConstraints: [NSLayoutConstraint
constraintsWithVisualFormat:@"H:|[subView(==parent)]"
options: 0
metrics: nil
views: views]];