设置约束,以便firstItem的top等于secondItem的高度

时间:2015-03-10 13:50:32

标签: ios autolayout nslayoutconstraint

我想设置top约束,使其与另一项height的关系相等。

我在界面构建器中准备它,以便第1项的top等于第2项的top

然后,在代码中(因为我认为它不能在Interface Builder中完成),我尝试设置约束的secondAttribute属性。

基于对约束如何组成的基本理解(两个项目,每个属性,关系类型和常量),这对我来说似乎合乎逻辑,但它不起作用:

@IBOutlet var fillTopToContainer: NSLayoutConstraint!
// ...
override func viewDidLoad() {
  fillTopToContainer.secondAttribute = NSLayoutAttribute.Height
}

Swift编译错误:

  

无法指定此表达式的结果。

我已经摆弄了常量以确保topDistEqualsHeight包含我期望的约束,并且它确实存在。约束中的其他值对我的需求是正确的,我只想更改属性。

这是一个已知的限制,语法问题,还是缺少大量知识?

更新

我也尝试了这个,它会引发运行时错误:

var pushTopDown = NSLayoutConstraint(item: self.view,
        attribute: NSLayoutAttribute.Height,
        relatedBy: NSLayoutRelation.Equal,
        toItem: fillRect,
        attribute: NSLayoutAttribute.Top,
        multiplier: 1,
        constant: -10)
    self.view.addConstraint(pushTopDown)

这是我想要实现的布局。它是一个滚动视图,正好是两个屏幕高,下半部分有填充颜色。

@ P-double建议fillRect将它的顶部与全高度对象的底部位置匹配,除非你不能将孙子的顶部相对于其祖父母在IB中设置。

查看层次结构:

  1. 框架(填充屏幕,根视图)
  2. scrollView(填充框架。内容大小由内部视图的约束决定)
  3. fillRect(height == frame,bottom == scrollView.bottom,top ==?)
  4. mockup

2 个答案:

答案 0 :(得分:3)

Constraint不会以您尝试使用它们的方式工作,最值得注意的是,除constant属性外,约束属性都是不可变的。

这种约束配对不起作用,因为一个与原点(y-positon)相关,一个与尺寸维相关。目前尚不清楚您想要实现的目标,但还有其他方法可以实现您想要的布局。如果您希望第二个视图位于第一个视图下方(在y平面中,它不一定必须对齐center-x位置),为什么不将第一个视图的底部固定到第二个视图的顶部?如果您想发布更多详情,我会尽力提供帮助。

修改

要实现所需的布局,您应将fillRect的顶部固定到scrollView的顶部,并使 约束保持帧高度 的值不变。比如这个

 var pushTopDown = NSLayoutConstraint(item: scrollView,
        attribute: NSLayoutAttribute.Top,
        relatedBy: NSLayoutRelation.Equal,
        toItem: fillRect,
        attribute: NSLayoutAttribute.Top,
        multiplier: 1,
        constant: self.view.height)
    scrollView.addConstraint(pushTopDown)

另请注意,约束已添加到滚动视图,而不是视图控制器视图。您还需要使fillRect的宽度等于scrollViews框架宽度。

正如@Rob指出的那样,你需要确保你还没有为top添加约束。如果视图没有完全受限,接口构建器会抱怨。诀窍是在界面构建器中添加顶部约束,但将其标记为设计时约束。要执行此操作,请在代码中选择要替换的约束,打开右侧的属性检查器,然后勾选“在构建时删除”选项。 (见图)这允许xib / storyboard无错误地编译,但实际上并没有将约束添加到视图中。

IB Screenshot

答案 1 :(得分:1)

底线,如果您尝试定义一个约束,使项目的“top”属性等于另一个的“height”属性,您将收到一条错误消息:

  

布局属性配对无效

底线,您无法在“顶部”和“高度”属性之间定义约束。

如果您想避免使用间隔视图,则在垂直间距视图时尝试的另一种方法是设置相对于超级视图.CenterYWithinMargins的{​​{1}}属性,并应用适当的倍数。您可以通过明智地使用每个项目的.CenterYWithinMargins属性的不同multiple值来平均视图。


关于您的一些尝试的一些观察结果:值得注意的是,您不能改变现有约束的.CenterY。创建约束后,只能修改secondAttribute属性。此外,在您对问题的更新中,您将说明创建新约束的尝试,并且您显然希望确保在创建新约束之前删除旧约束(或以较低优先级定义它)。


为了说明这个概念,这里是一个滚动视图,其中有一个屏幕外的着色视图都是以编程方式创建的(这是描述约束的最简洁方式,是方法):

constant