设置约束,使第一个项目的顶部等于第二个项目的高度
Set constraint so that firstItem's top equals secondItem's height
我想设置一个 top
约束,以便它具有与另一个项目的 height
.
相同的关系
我在 Interface Builder 中准备它,以便项目 1 的 top
等于项目 2 的 top
。
然后,在代码中(因为我不认为它可以在 Interface Builder 中完成),我尝试设置约束的 secondAttribute
属性.
基于对约束如何构成(由两个项目、每个项目的属性、关系类型和常数)的基本理解,这对我来说似乎合乎逻辑,但它不起作用:
@IBOutlet var fillTopToContainer: NSLayoutConstraint!
// ...
override func viewDidLoad() {
fillTopToContainer.secondAttribute = NSLayoutAttribute.Height
}
Swift编译错误:
Cannot assign to the result of this expression.
我摆弄了常量以确保 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 将它的顶部与全高度的底部位置相匹配 object,这会起作用,除非你不能相对于其祖父母设置孙子的顶部在 IB.
查看层次结构:
- 帧(填满屏幕,根视图)
- scrollView(填充框架。内容大小由内部视图的约束决定)
- fillRect (height==frame, bottom==scrollView.bottom, top==?)
约束不会以您尝试使用它们的方式工作,最值得注意的是约束属性除了 constant
属性.
之外都是不可变的
这对约束不起作用,因为一个与原点(y 位置)相关,一个与尺寸维度相关。目前尚不清楚您要实现的目标,但您可以通过其他方式实现所需的布局。如果您希望第二个视图位于第一个视图下方(在 y 平面中,它不一定必须对齐 center-x 位置),为什么不将第一个视图的底部固定到第二个视图的顶部?如果您想 post 了解更多详细信息,我会尽力提供帮助。
编辑
为了实现您想要的布局,您应该将 fillRect 的顶部固定到 scrollView 的顶部,并为 constraints 常量提供框架高度的值。比如这个
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 指出的那样,您需要确保尚未为顶部添加约束。如果视图没有完全约束,界面构建器会抱怨。诀窍是在界面构建器中添加一个顶级约束,但将其标记为设计时约束。为此,select 要在代码中替换的约束,打开右侧的属性检查器,然后勾选 'Remove at build time' 选项。 (见图片)这允许 xib/storyboard 编译而不会出错,但实际上并没有将约束添加到视图。
最重要的是,如果您尝试定义一个约束,使一个项目的 "top" 属性等于另一个项目的 "height" 属性,您将收到一条错误消息:
Invalid pairing of layout attributes
最重要的是,您不能在 "top" 和 "height" 属性之间定义约束。
如果您想避免使用 spacer 视图,另一种尝试垂直间隔视图的技术是相对于父视图的 .CenterYWithinMargins
设置 .CenterYWithinMargins
属性,应用合适的倍数。您同样可以 space 查看每个项目各自 .CenterY
属性的不同 multiple
值。
关于您的一些尝试的一些观察:值得注意的是,您不能改变现有约束的 secondAttribute
。创建约束后,只能修改 constant
属性。此外,在您对问题的更新中,您说明了创建新约束的尝试,并且您显然希望确保在创建新约束之前删除旧约束(或以较低的优先级定义它) .
为了说明这个概念,这里有一个带有着色视图的滚动视图,它在屏幕外都是以编程方式创建的(我认为这是描述约束的最简洁的方式):
let scrollView = UIScrollView()
scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
view.addSubview(scrollView)
let tintedView = UIView()
tintedView.setTranslatesAutoresizingMaskIntoConstraints(false)
tintedView.backgroundColor = UIColor.orangeColor()
scrollView.addSubview(tintedView)
let views = ["scrollView" : scrollView, "tintedView" : tintedView]
// vfl for `frame` of scrollView
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[scrollView]|", options: nil, metrics: nil, views: views))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView]|", options: nil, metrics: nil, views: views))
// vfl for `contentSize` of scrollView
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[tintedView]|", options: nil, metrics: nil, views: views))
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[tintedView]|", options: nil, metrics: nil, views: views))
// vfl for `frame` of tintedView
//
// (note, this can be integrated into the above constraints, reducing
// the extraneous VFL, but I implemented them as separate VFL to
// clearly differentiate between settings of the scrollView `contentSize`
// and the tintedView `frame`)
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[tintedView(==scrollView)]", options: nil, metrics: nil, views: views))
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[tintedView(==scrollView)]", options: nil, metrics: nil, views: views))
// offset tinted view
scrollView.addConstraint(NSLayoutConstraint(item: tintedView, attribute: .CenterY, relatedBy: .Equal, toItem: scrollView, attribute: .CenterY, multiplier: 3.0, constant: 0.0))
我想设置一个 top
约束,以便它具有与另一个项目的 height
.
我在 Interface Builder 中准备它,以便项目 1 的 top
等于项目 2 的 top
。
然后,在代码中(因为我不认为它可以在 Interface Builder 中完成),我尝试设置约束的 secondAttribute
属性.
基于对约束如何构成(由两个项目、每个项目的属性、关系类型和常数)的基本理解,这对我来说似乎合乎逻辑,但它不起作用:
@IBOutlet var fillTopToContainer: NSLayoutConstraint!
// ...
override func viewDidLoad() {
fillTopToContainer.secondAttribute = NSLayoutAttribute.Height
}
Swift编译错误:
Cannot assign to the result of this expression.
我摆弄了常量以确保 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 将它的顶部与全高度的底部位置相匹配 object,这会起作用,除非你不能相对于其祖父母设置孙子的顶部在 IB.
查看层次结构:
- 帧(填满屏幕,根视图)
- scrollView(填充框架。内容大小由内部视图的约束决定)
- fillRect (height==frame, bottom==scrollView.bottom, top==?)
约束不会以您尝试使用它们的方式工作,最值得注意的是约束属性除了 constant
属性.
这对约束不起作用,因为一个与原点(y 位置)相关,一个与尺寸维度相关。目前尚不清楚您要实现的目标,但您可以通过其他方式实现所需的布局。如果您希望第二个视图位于第一个视图下方(在 y 平面中,它不一定必须对齐 center-x 位置),为什么不将第一个视图的底部固定到第二个视图的顶部?如果您想 post 了解更多详细信息,我会尽力提供帮助。
编辑
为了实现您想要的布局,您应该将 fillRect 的顶部固定到 scrollView 的顶部,并为 constraints 常量提供框架高度的值。比如这个
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 指出的那样,您需要确保尚未为顶部添加约束。如果视图没有完全约束,界面构建器会抱怨。诀窍是在界面构建器中添加一个顶级约束,但将其标记为设计时约束。为此,select 要在代码中替换的约束,打开右侧的属性检查器,然后勾选 'Remove at build time' 选项。 (见图片)这允许 xib/storyboard 编译而不会出错,但实际上并没有将约束添加到视图。
最重要的是,如果您尝试定义一个约束,使一个项目的 "top" 属性等于另一个项目的 "height" 属性,您将收到一条错误消息:
Invalid pairing of layout attributes
最重要的是,您不能在 "top" 和 "height" 属性之间定义约束。
如果您想避免使用 spacer 视图,另一种尝试垂直间隔视图的技术是相对于父视图的 .CenterYWithinMargins
设置 .CenterYWithinMargins
属性,应用合适的倍数。您同样可以 space 查看每个项目各自 .CenterY
属性的不同 multiple
值。
关于您的一些尝试的一些观察:值得注意的是,您不能改变现有约束的 secondAttribute
。创建约束后,只能修改 constant
属性。此外,在您对问题的更新中,您说明了创建新约束的尝试,并且您显然希望确保在创建新约束之前删除旧约束(或以较低的优先级定义它) .
为了说明这个概念,这里有一个带有着色视图的滚动视图,它在屏幕外都是以编程方式创建的(我认为这是描述约束的最简洁的方式):
let scrollView = UIScrollView()
scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
view.addSubview(scrollView)
let tintedView = UIView()
tintedView.setTranslatesAutoresizingMaskIntoConstraints(false)
tintedView.backgroundColor = UIColor.orangeColor()
scrollView.addSubview(tintedView)
let views = ["scrollView" : scrollView, "tintedView" : tintedView]
// vfl for `frame` of scrollView
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[scrollView]|", options: nil, metrics: nil, views: views))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView]|", options: nil, metrics: nil, views: views))
// vfl for `contentSize` of scrollView
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[tintedView]|", options: nil, metrics: nil, views: views))
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[tintedView]|", options: nil, metrics: nil, views: views))
// vfl for `frame` of tintedView
//
// (note, this can be integrated into the above constraints, reducing
// the extraneous VFL, but I implemented them as separate VFL to
// clearly differentiate between settings of the scrollView `contentSize`
// and the tintedView `frame`)
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[tintedView(==scrollView)]", options: nil, metrics: nil, views: views))
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[tintedView(==scrollView)]", options: nil, metrics: nil, views: views))
// offset tinted view
scrollView.addConstraint(NSLayoutConstraint(item: tintedView, attribute: .CenterY, relatedBy: .Equal, toItem: scrollView, attribute: .CenterY, multiplier: 3.0, constant: 0.0))