没有内在尺寸的自动布局
Posted
技术标签:
【中文标题】没有内在尺寸的自动布局【英文标题】:Autolayout without intrinsic size 【发布时间】:2021-11-20 07:47:18 【问题描述】:谁能告诉我 Autolayout 如何知道 UIView 的大小,它没有固有大小并且只有一个维度受到限制?
例如,我有一个包含一组子视图的普通视图。视图被限制在父级的前后页边距并垂直居中。 Autolayout 能够向视图询问给定宽度的高度,但我不知道如何。我需要手动布局子视图,但看不到需要实现的功能/属性,因此 Autolayout 可以告诉我宽度并询问相应的高度。
有人知道吗?
【问题讨论】:
“我需要手动布置子视图”——你是说在 Storyboard 中吗?或者你的意思是通过代码?一般来说,你要么给视图一个高度,并让约束布局它的子视图,或者......你让子视图上的约束决定视图的高度。 在代码中。我不能在这个视图中使用自动布局,因为布局很复杂。我知道如果可以的话,一切都会奏效。 【参考方案1】:作为一般规则,布局越复杂,更多使用自动布局的理由。
但是,如果您真的想“手动布局”您的子视图并计算内在大小,您可以通过覆盖 intrinsicContentSize
来实现。
因此,例如,如果您计算layoutSubviews()
中的子视图大小/位置,您还应该计算那里的高度,调用invalidateIntrinsicContentSize()
,并返回您计算的高度。
这是一个简单的例子。我们添加两个子视图,一个在另一个之上。我们给顶视图一个 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),
])
我们得到这个输出:
【讨论】:
感谢 DonMag 的全面建议,这是一个有趣的想法。它归结为返回“noIntrinsicSize”的初始固有宽度和零高度,并且在 layoutSubviews 的第一遍使用 bounds.width 来计算高度。我会试试看。 @jspinks - 如果您想查看更“实用”的示例,请查看此答案的 Edit 部分中的TagLabelsView
类:@987654323 @以上是关于没有内在尺寸的自动布局的主要内容,如果未能解决你的问题,请参考以下文章