以编程方式自动布局不垂直居中

Posted

技术标签:

【中文标题】以编程方式自动布局不垂直居中【英文标题】:Programmatically autolayout not centering vertically 【发布时间】:2015-04-09 19:04:13 【问题描述】:

我想使用自动布局将视图垂直和水平居中,但不知何故我在这样做时遇到了麻烦。我在 ios8 模拟器和 iOS8 设备上运行。我尝试过两种版本的代码,但都没有。以下是sn-ps:

首先让我们分配我们正在使用的视图:

UIView *inputView = UIView.new; //Don't hate me for the dot syntax :)
inputView.translatesAutoresizingMaskIntoConstraints = NO;
inputView.backgroundColor = UIColor.redColor;

[self.view addSubview:inputView];

尝试 #1:

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:inputView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0.0f]; //Center the view horizontally
[self.view addConstraint:constraint];

constraint = [NSLayoutConstraint constraintWithItem:inputView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1.0f constant:0.0f]; //And make it have the same width as the view
[self.view addConstraint:constraint];

constraint = [NSLayoutConstraint constraintWithItem:inputView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0f constant:260.0f]; //Force exactly 260pts view height
[inputView addConstraint:constraint]; //If I add it to self.view it's the same thing

constraint = [NSLayoutConstraint constraintWithItem:inputView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:0.5f constant:0.0f]; //And try to center it vertically - DOES NOT WORK... wtf
[self.view addConstraint:constraint];

对我来说似乎是一段完全合法的代码。但是没有。

尝试 #2。基本上是一样的,代码行数更少。

NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-[inputView(>=320)]-|" options:NSLayoutFormatAlignAllCenterX metrics:nil views:NSDictionaryOfVariableBindings(inputView)];
[self.view addConstraints:constraints];

constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[inputView(260)]-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(inputView)];
[self.view addConstraints:constraints];

现在这个也不起作用。我的意思是它确实使视图水平居中,但是当我添加垂直约束时,我确实收到一条警告,告诉我我不擅长自动布局。它说它无法满足所有约束。更具体地说:

(
    "<NSLayoutConstraint:0x17408be00 UIView:0x174197010.top == UIView:0x174196da0.topMargin>",
    "<NSLayoutConstraint:0x17408bdb0 V:[UIView:0x174197010(260)]>",
    "<NSLayoutConstraint:0x17408bd60 UIView:0x174196da0.bottomMargin == UIView:0x174197010.bottom>",
    "<NSLayoutConstraint:0x17008a000 'UIView-Encapsulated-Layout-Height' V:[UIView:0x174196da0(667)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x17408bd60 UIView:0x174196da0.bottomMargin == UIView:0x174197010.bottom>

我不确定如何解决这个问题。下面是我从尝试 #1 和 #2 得到的结果图片。

我该如何解决?

【问题讨论】:

用点语法大声笑。让我猜猜:你的 UIView 扩展名为 UIView+Swift! 不,实际上都是 ObjC :) 我认为这是 Apple 很久以前推出的一个非常蹩脚的东西。它没有显示在语法完成中,但仍然可以编译。试试看。如果发现它比[UIView new] 更干净。 【参考方案1】:

在设置垂直约束时,您将乘数设置为 0.5f,这是导致此问题的原因。将其设置为 1.0f,就像您为水平约束设置的那样。

constraint = [NSLayoutConstraint constraintWithItem:inputView
                                          attribute:NSLayoutAttributeCenterY
                                          relatedBy:NSLayoutRelationEqual
                                             toItem:self.view
                                          attribute:NSLayoutAttributeCenterY
                                         multiplier:1.0f
                                           constant:0.0f];

【讨论】:

啊当然!我一直在想“好吧,这需要是整个高度的一半”,这就是 0.5 的来源。固定。【参考方案2】:

你不断地重新定义constraint。你需要有xconstraintyconstraintwconstrainthconstraint 之类的东西。然后将每个约束添加到 self.view 或[self.view addConstraints:@[xconstraint, yconstraint,...];

您可能还需要致电[self.view layoutIfNeeded];

更新

Y 约束的乘数必须是 1.0,而不是 0.5。

【讨论】:

不,这不是必需的。由于NSLayoutConstraint *constraint 只是一个指向约束的指针,一旦我向视图添加约束(即addConstraint:),该视图就会对它进行强引用。因此,在执行constraint = [new constraint] 时,我只是在更改指针。至于layoutIfNeeded 不行。 如果你在layoutIfNeeded之前也调用setNeedsLayout会发生什么? 已更新答案。你是复制粘贴之类的受害者。

以上是关于以编程方式自动布局不垂直居中的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式自动布局不起作用

ios 6:使用自动布局约束垂直居中 UILabel

使用 UILabel 以编程方式自动布局不起作用

剩余空间中的自动布局居中视图(以编程方式)

以编程方式自动布局垂直ios时出错

自动布局 - 以编程方式垂直排列元素,中间有空格?