没有固有尺寸的自动布局
Autolayout without intrinsic size
谁能告诉我 Autolayout 是如何知道 UIView 的大小的,它没有固有大小,只有一个维度受到约束?
例如,我有一个包含一组子视图的普通视图。视图受限于父级的前导和尾随边距,并垂直居中。自动布局能够向视图询问给定宽度的高度,但我不知道如何。我需要手动布局子视图,但我看不到我需要实现哪个 function/property,因此 Autolayout 可以告诉我宽度并要求相应的高度。
有人知道吗?
一般来说,布局越复杂,更多使用自动布局的理由。
但是,如果您真的想“手动布局”您的子视图并计算固有大小,您可以通过重写 intrinsicContentSize
.
来实现
因此,例如,如果您计算您在layoutSubviews()
中的子视图大小/位置,您还应该计算那里的高度,调用invalidateIntrinsicContentSize()
,和 return 您计算出的身高。
这是一个简单的例子。我们添加两个子视图,一个在另一个之上。我们给顶视图一个 4:1 比例,给底视图一个 3:1 比例。
class MyIntrinsicView: UIView {
var myHeight: CGFloat = 0
let view1: UIView = {
let v = UIView()
v.backgroundColor = .red
return v
}()
let view2: UIView = {
let v = UIView()
v.backgroundColor = .green
return v
}()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
addSubview(view1)
addSubview(view2)
backgroundColor = .blue
}
override var intrinsicContentSize: CGSize {
var sz = super.intrinsicContentSize
sz.height = myHeight
return sz
}
override func layoutSubviews() {
super.layoutSubviews()
// let's say view 1 needs a 4:1 ratio and
// view 2 needs a 3:1 ratio
view1.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.width / 4.0)
view2.frame = CGRect(x: 0, y: view1.frame.maxY, width: bounds.width, height: bounds.width / 3.0)
myHeight = view1.frame.height + view2.frame.height
invalidateIntrinsicContentSize()
}
}
使用这个示例视图控制器,我们给视图 60 磅的前导和尾随,并且只有 centerY 约束:
class QuickExampleViewController: UIViewController {
let testView = MyIntrinsicView()
override func viewDidLoad() {
super.viewDidLoad()
testView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(testView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
testView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 60.0),
testView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -60.0),
testView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
])
}
}
我们得到这个输出:
谁能告诉我 Autolayout 是如何知道 UIView 的大小的,它没有固有大小,只有一个维度受到约束?
例如,我有一个包含一组子视图的普通视图。视图受限于父级的前导和尾随边距,并垂直居中。自动布局能够向视图询问给定宽度的高度,但我不知道如何。我需要手动布局子视图,但我看不到我需要实现哪个 function/property,因此 Autolayout 可以告诉我宽度并要求相应的高度。
有人知道吗?
一般来说,布局越复杂,更多使用自动布局的理由。
但是,如果您真的想“手动布局”您的子视图并计算固有大小,您可以通过重写 intrinsicContentSize
.
因此,例如,如果您计算您在layoutSubviews()
中的子视图大小/位置,您还应该计算那里的高度,调用invalidateIntrinsicContentSize()
,和 return 您计算出的身高。
这是一个简单的例子。我们添加两个子视图,一个在另一个之上。我们给顶视图一个 4:1 比例,给底视图一个 3:1 比例。
class MyIntrinsicView: UIView {
var myHeight: CGFloat = 0
let view1: UIView = {
let v = UIView()
v.backgroundColor = .red
return v
}()
let view2: UIView = {
let v = UIView()
v.backgroundColor = .green
return v
}()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
addSubview(view1)
addSubview(view2)
backgroundColor = .blue
}
override var intrinsicContentSize: CGSize {
var sz = super.intrinsicContentSize
sz.height = myHeight
return sz
}
override func layoutSubviews() {
super.layoutSubviews()
// let's say view 1 needs a 4:1 ratio and
// view 2 needs a 3:1 ratio
view1.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.width / 4.0)
view2.frame = CGRect(x: 0, y: view1.frame.maxY, width: bounds.width, height: bounds.width / 3.0)
myHeight = view1.frame.height + view2.frame.height
invalidateIntrinsicContentSize()
}
}
使用这个示例视图控制器,我们给视图 60 磅的前导和尾随,并且只有 centerY 约束:
class QuickExampleViewController: UIViewController {
let testView = MyIntrinsicView()
override func viewDidLoad() {
super.viewDidLoad()
testView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(testView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
testView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 60.0),
testView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -60.0),
testView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
])
}
}
我们得到这个输出: