最近一直在进入自动布局,我被困在一个看似非常微不足道的问题示例上。我有一个视图,我想坐在屏幕的顶部,并占据屏幕高度的一半。在自动布局之前很简单 - 只需将其固定到位并在超级视图调整大小时告诉它垂直扩展。
现在,我一辈子都看不到该怎么做。这是我尝试设置时得到的结果:
https://i.stack.imgur.com/Lo413.png
底部空间约束设置为“等于 284”,当我更改为 iPhone4 布局时,这对我来说绝对无用,因为它在屏幕底部保留 284 点空间,并将视图缩小到不再是一半屏幕的大小。并且没有办法将该约束设置为等于任何其他视图高度的一部分。
挣扎了一段时间后,我能想到的唯一方法是在该视图下方引入另一个视图,将它们的高度固定,让它们彼此上下放置,然后将第二个(底部)视图设置为不可见..这似乎有点难看!
我错过了什么明显的东西吗?
故事板解决方案,您可以在其中设置任何视图之间的精确比例:
https://i.stack.imgur.com/dHwom.png
现在:
https://i.stack.imgur.com/64SDU.png
利润!!!
https://i.stack.imgur.com/8Im6S.png
PS 另请注意,此方法适用于不同嵌套级别的视图,并且(显然)适用于宽度
PPS 有时可能有助于“反转第一项和第二项”约束或设置反向乘数(例如 2 而不是 0.5)(但如果您不了解视图之间的相互关系,这些方法将无济于事)。
从 [至少] Xcode 5.1.1 开始,现在这在 IB 中是可能的。虽然我花了一些时间才弄清楚它实际上非常简单:
首先创建一个基本的顶部对齐约束(您还需要像正常一样设置底部、左侧和右侧约束)。然后选择约束并导航到属性检查器:
https://i.stack.imgur.com/OuxVA.png
然后你可以调整乘数。如果您想要 50% 的超级视图,请将其保留在 1
,因为它与超级视图的中心对齐。这也是创建其他百分比的视图的好方法(例如 25% 的超级视图)
https://i.stack.imgur.com/jDvj0.png
First Item
是 View.Top
而不是 View.Center Y
。否则,是的,它只会居中。您还需要确保正确设置其他约束以处理视图的其他边缘。
再过一段时间后,我想出了以下内容。
我注意到它是一个答案,但它并不是很令人满意,因为它假设您实际上不能在 Interface Builder 中执行此操作,但可以在代码中添加正确的约束,如下所示:
- (void) viewWillAppear:(BOOL)animated
{
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:upperview
attribute:NSLayoutAttributeHeight
relatedBy:0
toItem:self.view
attribute:NSLayoutAttributeHeight
multiplier:.5
constant:0];
[self.view addConstraint:constraint];
}
基本上,它对 self.view 的高度设置了 0.5 的乘数,作用于上视图。我不得不将 IB 中底部垂直空间约束的优先级设置为低于 1000,以避免出现一堆关于破坏约束的运行时消息。
因此,如果有人可以在 Interface Builder 中展示如何做到这一点,那将更好地回答我的问题,否则我想这已经很好了(目前)???
比方法比 Fyodor Volchyok 的答案更容易和更直接。 - 按住控制按钮并单击子视图。 - 仍然按住命令按钮,将光标拖动到超级视图,然后单击超级视图。 - 选择“纵横比”。
https://i.stack.imgur.com/zVcWY.png
https://i.stack.imgur.com/n7uPG.png
https://i.stack.imgur.com/nkHHM.png
https://i.stack.imgur.com/dDTLw.png
如果您有 2 个视图应该具有相同的高度,我在代码中还有另一种可能性:只需将 view2 的高度设置为 view1 的高度(这里的技巧是不明确设置 view1 的高度)。
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:[topLayoutGuide]-0-[_view1]-0-[_view2(==_view1)]-0-[bottomLayoutGuide]"
options:0
metrics:nil
views:viewsDict]];
Mete 回答的 Swift 版本:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
upperView.translatesAutoresizingMaskIntoConstraints = false
var constraint = NSLayoutConstraint(item: upperView,
attribute: NSLayoutAttribute.top,
relatedBy: NSLayoutRelation.equal,
toItem: self.view,
attribute: NSLayoutAttribute.top,
multiplier: 1,
constant: 0)
self.view.addConstraint(constraint)
constraint = NSLayoutConstraint(item: upperView,
attribute: NSLayoutAttribute.height,
relatedBy: NSLayoutRelation.equal,
toItem: self.view,
attribute: NSLayoutAttribute.height,
multiplier: 0.5,
constant: 0)
self.view.addConstraint(constraint)
constraint = NSLayoutConstraint(item: upperView,
attribute: NSLayoutAttribute.leading,
relatedBy: NSLayoutRelation.equal,
toItem: self.view,
attribute: NSLayoutAttribute.leading,
multiplier: 1,
constant: 0)
self.view.addConstraint(constraint)
constraint = NSLayoutConstraint(item: upperView,
attribute: NSLayoutAttribute.trailing,
relatedBy: NSLayoutRelation.equal,
toItem: self.view,
attribute: NSLayoutAttribute.trailing,
multiplier: 1,
constant: 0)
self.view.addConstraint(constraint)
}