如何使用自动布局约束来定义和定位嵌入式UIViewController?

时间:2016-03-18 14:05:21

标签: ios uiviewcontroller autolayout interface-builder xcode7

这是我想做的事情: 我的故事板包含UIViewController只有几个控件。它的高度不到半个屏幕。为简单起见,我们称之为DataViewControllerDataViewController通过“UIViewControllers”嵌入其他Container View内。

虽然“Container View”显示DataViewController,但仍需要设置明确的height。否则,界面构建器会抱怨模糊约束。

现在,我怎么能告诉“Container View”它的大小应该是DataViewController所要求的大小?即没有在Interface Builder中设置硬编码的显式height(我担心,如果字体大小改变,会破坏布局)?

或换句话说:如何在Interface Builder中对嵌入式UIViewControllers进行大小/定位?

3 个答案:

答案 0 :(得分:9)

如果你想让childViewContainer负责它的宽度和高度,可以采用以下方法:

  • 在父视图控制器中设置宽度和高度约束,然后在构建时选择删除。它们只是在这里,所以界面构建器停止抱怨缺少约束。 enter image description here

  • (您可以)在故事板大小检查器选项卡中将您的子视图控制器模拟大小从固定更改为自由形式。

enter image description here

  • 这是诀窍:在您的父视图控制器viewDidLoad中禁用translatesAutoresizingMaskIntoConstraints在第一个子视图上,只需将自己的containerView约束重新定义到其子视图 - 您的子视图控制器的根视图 - 如下所示:

<强>目标C

- (void)viewDidLoad {
    [super viewDidLoad];
    self.containerView.subviews[0].translatesAutoresizingMaskIntoConstraints = NO;
}

#pragma mark - Constraints

- (void)updateViewConstraints {
    [super updateViewConstraints];
    [self initConstraints];
}

- (void)initConstraints {
    if (!self.didSetConstraints) {
        self.didSetConstraints = YES;

        self.containerView.subviews[0].translatesAutoresizingMaskIntoConstraints = NO;

        NSDictionary *views = @{@"subview" : self.containerView.subviews[0]};

        [self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subview]|" options:0 metrics:nil views:views]];
        [self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[subview]|" options:0 metrics:nil views:views]];
    }
}

<强>夫特

override func viewDidLoad() {
    super.viewDidLoad()
    containerView.subviews[0].translatesAutoresizingMaskIntoConstraints = false
}

// Mark: Constraints

override func updateViewConstraints() {
    super.updateViewConstraints()
    initConstraints()
}

func initConstraints() {
    if !didSetConstraints {
        didSetConstraints = true

        containerView.subviews[0].translatesAutoresizingMaskIntoConstraints = false

        let views = ["subview": containerView.subviews[0]]

        containerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[subview]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
        containerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[subview]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
    }
}

现在,您的子视图控制器(链接到容器视图)对其内容大小负全部责任。因此,必须设置约束,让根视图计算其大小以满足其所拥有的约束。

答案 1 :(得分:2)

如果您使用 segue 嵌入,请执行以下操作:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let viewController = segue.destination as? EmbeddedViewController {
      viewController.view.translatesAutoresizingMaskIntoConstraints = false
    }
}

答案 2 :(得分:0)

在内容视图控制器中,按如下所示设置preferredContentSize(在您的示例DataViewController中)

override func viewDidLoad() {
    super.viewDidLoad()
    preferredContentSize = CGSize(width: 400, height: 200)
}

当孩子被添加到parentViewController时,parentViewController会收到有关首选大小的通知。在父级

上调用以下函数 func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer)

通过这种方法,您可以将容器更改为孩子喜欢的尺寸。
例如,将高度更改为孩子/内容的首选高度

override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) {
    // heightConstraint is a IBOutlet to your NSLayoutConstraint you want to adapt to height of your content
    heigtConstraint.constant = container.preferredContentSize.height
}