也许这是我的设置代码对UIView
的frame
属性的滥用,对于自动布局视图,其中,因为我假设视图的初始frame
属性值一旦添加了自动布局约束就不重要了,我可以使用frame.origin
来缓存在坐标空间中不是真正视图原点的值。
我所说的"滥用"是什么意思?我将frame.origin
设置为约束设置函数调用中的参数值,因为我喜欢在我的代码中通过CGRect调整约束偏移的简洁性和便利性。但也许适得其反?不知道为什么……
例如:
let view = UIView(frame: CGRect(x: 10, y: 10, width: 100, height: 100))
NSLayoutConstraint.activate([
view.leadingAnchor.constraint(equalTo: leftSideView.trailingAnchor,
constant: view.frame.origin.x)
.
.
.
])
最初看起来很好,视图按预期放置在屏幕上,但在视图被AutoLayout布局后,frame.origin
似乎反映了我最初的盗用…例如,在自动布局之后,frame.origin
仍然是(10,10)…反正在AutoLayout之后,frame.origin
都是不是在坐标系中的正确绝对值一般指的是frame属性来获取。
我这样做之后:
view.setNeedLayout()
view.layoutIfNeeded()
当我打印框架时。原点值,它们不是视图的实际位置。
为什么不呢?那么,我怎样才能找到正确的值呢?
也许我需要调用一个UIView的父视图坐标转换函数?
UPDATE:没有其原点集的视图实际上是leftSideView,我使用与我约束的视图相同的方法配置。我确实运行setNeedsLayout()/layout,但现在我认为自动布局还没有足够的数据来计算帧,所以我有一个先有蛋的问题,我试图添加基于约束的约束尚未解决,这将不起作用
您正在要求错误的视图布局。view
没有太多的布局,除了它自己的大小。它不知道如何布局自己相对于leftSideView
,因为leftSideView
不是它的子视图之一。
布局view
相对于leftSideView
,找到他们共同的父,并要求它布局。假设view.superview
是共同的父节点,执行:
view.superview!.layoutIfNeeded()
那么view.frame
将是您期望的值。
或者,您可以在您想要布局的视图的公共父视图的UIViewController
或layoutSubviews
中覆盖viewDidLayoutSubviews
,以检测布局何时完成,而无需调用layoutIfNeeded
。在这里,frame
也会有正确的值。
最小的例子:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let v = UIView(frame: .zero)
view.addSubview(v)
v.backgroundColor = .blue
v.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
v.topAnchor.constraint(equalTo: view.topAnchor, constant: 10),
v.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30),
v.widthAnchor.constraint(equalToConstant: 100),
v.heightAnchor.constraint(equalToConstant: 100)
])
let u = UIView(frame: .init(x: 10, y: 10, width: 100, height: 100))
view.addSubview(u)
u.backgroundColor = .red
u.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
u.topAnchor.constraint(equalTo: v.bottomAnchor, constant: 10),
u.leftAnchor.constraint(equalTo: v.leftAnchor),
u.widthAnchor.constraint(equalToConstant: 100),
u.heightAnchor.constraint(equalToConstant: 100)
])
// before any layout
print(u.frame)
// laying out u, doesn't change anything
u.layoutIfNeeded()
// note that the above could change the frame of u depending on the frame
// of u and its size constraints, but I've deliberately chosen these
// values and constraints so that it matches your behaviour
print(u.frame)
// laying out u, and v, making u.frame what you expect
view.layoutIfNeeded() // view is the common parent between u and v
print(u.frame)
}
}