更新 Frame/Constraints 以便在方向更改时以编程方式添加 UIView
Updating Frame/Constraints for programmatically added UIView on orientation change
我有一个 UIView,我正在使用 viewDidLoad 中的以下代码以编程方式添加它
dropMenuView = YNDropDownMenu(frame: CGRect(x: 0.0, y: 0, width: UIScreen.main.bounds.width, height: 40.0), dropDownViews: [typeView, brandView, priceView], dropDownViewTitles:["Type", "Brand", "Price"])
self.view.addSubview(dropMenuView)
以上代码为当前方向创建了一个具有正确宽度的视图,但是如果用户改变了他们的设备方向,视图的宽度不会更新。我尝试在 viewWillTransitionTo:
中添加新约束
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
let widthConstraint = NSLayoutConstraint(item: dropMenuView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)
dropMenuView.addConstraints([widthConstraint])
dropMenuView.layoutIfNeeded()
}
我已经对上面的代码进行了多次修改,试图使其正常工作。通常我得到的错误是:
'NSLayoutConstraint for >: Unknown layout attribute'
我不禁觉得我的做法是错误的。在方向上添加新的约束是否会改变方向?我尝试在添加子视图后添加等宽约束,但我得到了同样的错误。我以前从未真正以编程方式添加过约束,所以这些对我来说是未知领域。这里最好的方法是什么?
在方向更改期间添加约束不是一个好主意。如果您要这样做,您需要删除之前添加的约束以避免过度约束您的视图。
您尝试创建的约束不正确。当你传递 nil
作为第二个视图时,你只使用 .notAnAttrubute
。
我建议您改为使用布局锚点。它们更易于编写和阅读:
dropMenuView = YNDropDownMenu(frame: CGRect.zero, dropDownViews: [typeView, brandView, priceView], dropDownViewTitles:["Type", "Brand", "Price"])
self.view.addSubview(dropMenuView)
// you need to set this if you are adding your own constraints and once
// yet set it, the frame is ignored (which is why we just passed CGRect.zero
// when creating the view)
dropMenuView.translatesAutoresizingMaskIntoConstraints = false
// Create the constraints and activate them. This will set `isActive = true`
// for all of the constraints. iOS knows which views to add them to, so
// you don't have to worry about that detail
NSLayoutConstraint.activate([
dropMenuView.topAnchor.constraint(equalTo: view.topAnchor),
dropMenuView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
dropMenuView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
dropMenuView.heightAnchor.constraint(equalToConstant: 40)
])
我有一个 UIView,我正在使用 viewDidLoad 中的以下代码以编程方式添加它
dropMenuView = YNDropDownMenu(frame: CGRect(x: 0.0, y: 0, width: UIScreen.main.bounds.width, height: 40.0), dropDownViews: [typeView, brandView, priceView], dropDownViewTitles:["Type", "Brand", "Price"])
self.view.addSubview(dropMenuView)
以上代码为当前方向创建了一个具有正确宽度的视图,但是如果用户改变了他们的设备方向,视图的宽度不会更新。我尝试在 viewWillTransitionTo:
中添加新约束override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
let widthConstraint = NSLayoutConstraint(item: dropMenuView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)
dropMenuView.addConstraints([widthConstraint])
dropMenuView.layoutIfNeeded()
}
我已经对上面的代码进行了多次修改,试图使其正常工作。通常我得到的错误是: 'NSLayoutConstraint for >: Unknown layout attribute'
我不禁觉得我的做法是错误的。在方向上添加新的约束是否会改变方向?我尝试在添加子视图后添加等宽约束,但我得到了同样的错误。我以前从未真正以编程方式添加过约束,所以这些对我来说是未知领域。这里最好的方法是什么?
在方向更改期间添加约束不是一个好主意。如果您要这样做,您需要删除之前添加的约束以避免过度约束您的视图。
您尝试创建的约束不正确。当你传递 nil
作为第二个视图时,你只使用 .notAnAttrubute
。
我建议您改为使用布局锚点。它们更易于编写和阅读:
dropMenuView = YNDropDownMenu(frame: CGRect.zero, dropDownViews: [typeView, brandView, priceView], dropDownViewTitles:["Type", "Brand", "Price"])
self.view.addSubview(dropMenuView)
// you need to set this if you are adding your own constraints and once
// yet set it, the frame is ignored (which is why we just passed CGRect.zero
// when creating the view)
dropMenuView.translatesAutoresizingMaskIntoConstraints = false
// Create the constraints and activate them. This will set `isActive = true`
// for all of the constraints. iOS knows which views to add them to, so
// you don't have to worry about that detail
NSLayoutConstraint.activate([
dropMenuView.topAnchor.constraint(equalTo: view.topAnchor),
dropMenuView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
dropMenuView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
dropMenuView.heightAnchor.constraint(equalToConstant: 40)
])