当视图大小不同时如何以编程方式设置约束?
How to programmatically set constraints when View sizes are different?
使用 Xcode 10,iOS 11.4+,Swift 4
我正在浏览一系列 UIViewController,
每个都被放入一个 ContainerView 中。
基于VC被推送,我hiding/showing主控制器中的顶部或底部视图(以灰色显示),而ContainerView始终在中间(浅蓝色)。
我想做的是设置约束,以便在顶视图或底视图为 shown/hidden 时适当调整 ContainerView 的大小。
例如,当 "Main Menu" 显示时,ContainerView 应填充整个 Main Container 视图(Top 和 Bottom 视图将被隐藏)
显示"Item1"时,会显示顶视图,隐藏底视图。因此,ContainerView 应填充 Main Container 视图的左、右和底部,但 ContainerView Top 应限制在 Top 视图底部。
显示 "Item5" 时,顶视图和底视图也会显示。
因此,ContainerView应该填充Main Container view left, right,并被约束在Top view bottom,Bottom view top(如Main Container所示)
我试过使用这样的代码来填充整个主视图:
NSLayoutConstraint.activate([
ContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0),
ContainerView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0),
ContainerView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0),
ContainerView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0)
])
但是,ContainerView 永远不会改变,Xcode 给了我很多警告,例如:
[LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one
you don't want.
这是情节提要中的另一个屏幕截图:
这里是 link 下载我的示例项目:
https://gitlab.com/whoit/containerviews
如何正确修改约束以实现此目的?
正如我在评论中提到的,您应该使用 UIStackView
来控制顶部/底部视图的可见性。
您需要 UIStackView
具有以下属性:
- 轴:垂直
- 对齐方式:填充
- 分配:填充
- 间距:根据您的需要
堆栈视图将分别包含顶部视图、容器视图和底部视图作为其子视图。
您需要将此堆栈视图的所有边(前导、尾随、顶部和底部)固定到其父视图(视图控制器的视图)。由于您的顶视图和底视图需要一些高度限制,因此您可以根据需要提供它们。
所以基本上,当您隐藏其中任何一个时,您的堆栈视图现在能够调整其子视图的大小。您只需要执行:
theSubViewNeedsTobeHidden.isHidden = true
我已经为您制作了一个可以工作的演示 here。
问题
1) 你一直在添加新的约束,因为这行创建了一个新的约束,每次它们被调用时:
ContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0)
2) 一开始,MainContainerView
根本不是约束
解决方案
我建议如下:
- 改为在故事板中添加这四个约束
- 为顶部和底部视图的高度限制创建 IBOutlets。
- 将它们的
constant
设置为 0
(隐藏它们时)
- (可选)当然你仍然可以通过设置它们的
alpha
来淡化它们 in/out,然后将高度常量添加到完成块。
注意:
布局时仍会考虑隐藏视图(alpha = 0
或 isHidden = true
)。这意味着,当视图被隐藏时,您的约束仍然有效。但是为了使它们在布局中看起来也隐藏起来,您必须将它们的高度 constant
s 设置为 0
.
代码
@objc func hideControlViews(_ notification: Notification){
let userInfo = notification.userInfo! as! [String : Bool]
//print("Got top view notification: \(String(describing: userInfo["hide"]))")
if (userInfo["hidetop"]!) {
self.topViewHeightConstraint.constant = 0
} else {
self.topViewHeightConstraint.constant = 64
}
if (userInfo["hidebottom"]!) {
self.bottomViewHeightConstraint.constant = 0
} else {
self.bottomViewHeightConstraint.constant = 108
}
self.view.layoutIfNeeded()
}
使用 Xcode 10,iOS 11.4+,Swift 4
我正在浏览一系列 UIViewController, 每个都被放入一个 ContainerView 中。
基于VC被推送,我hiding/showing主控制器中的顶部或底部视图(以灰色显示),而ContainerView始终在中间(浅蓝色)。
我想做的是设置约束,以便在顶视图或底视图为 shown/hidden 时适当调整 ContainerView 的大小。
例如,当 "Main Menu" 显示时,ContainerView 应填充整个 Main Container 视图(Top 和 Bottom 视图将被隐藏)
显示"Item1"时,会显示顶视图,隐藏底视图。因此,ContainerView 应填充 Main Container 视图的左、右和底部,但 ContainerView Top 应限制在 Top 视图底部。
显示 "Item5" 时,顶视图和底视图也会显示。 因此,ContainerView应该填充Main Container view left, right,并被约束在Top view bottom,Bottom view top(如Main Container所示)
我试过使用这样的代码来填充整个主视图:
NSLayoutConstraint.activate([
ContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0),
ContainerView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0),
ContainerView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0),
ContainerView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0)
])
但是,ContainerView 永远不会改变,Xcode 给了我很多警告,例如:
[LayoutConstraints] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want.
这是情节提要中的另一个屏幕截图:
这里是 link 下载我的示例项目: https://gitlab.com/whoit/containerviews
如何正确修改约束以实现此目的?
正如我在评论中提到的,您应该使用 UIStackView
来控制顶部/底部视图的可见性。
您需要 UIStackView
具有以下属性:
- 轴:垂直
- 对齐方式:填充
- 分配:填充
- 间距:根据您的需要
堆栈视图将分别包含顶部视图、容器视图和底部视图作为其子视图。
您需要将此堆栈视图的所有边(前导、尾随、顶部和底部)固定到其父视图(视图控制器的视图)。由于您的顶视图和底视图需要一些高度限制,因此您可以根据需要提供它们。
所以基本上,当您隐藏其中任何一个时,您的堆栈视图现在能够调整其子视图的大小。您只需要执行:
theSubViewNeedsTobeHidden.isHidden = true
我已经为您制作了一个可以工作的演示 here。
问题
1) 你一直在添加新的约束,因为这行创建了一个新的约束,每次它们被调用时:
ContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0)
2) 一开始,MainContainerView
根本不是约束
解决方案
我建议如下:
- 改为在故事板中添加这四个约束
- 为顶部和底部视图的高度限制创建 IBOutlets。
- 将它们的
constant
设置为0
(隐藏它们时) - (可选)当然你仍然可以通过设置它们的
alpha
来淡化它们 in/out,然后将高度常量添加到完成块。
注意:
布局时仍会考虑隐藏视图(alpha = 0
或 isHidden = true
)。这意味着,当视图被隐藏时,您的约束仍然有效。但是为了使它们在布局中看起来也隐藏起来,您必须将它们的高度 constant
s 设置为 0
.
代码
@objc func hideControlViews(_ notification: Notification){
let userInfo = notification.userInfo! as! [String : Bool]
//print("Got top view notification: \(String(describing: userInfo["hide"]))")
if (userInfo["hidetop"]!) {
self.topViewHeightConstraint.constant = 0
} else {
self.topViewHeightConstraint.constant = 64
}
if (userInfo["hidebottom"]!) {
self.bottomViewHeightConstraint.constant = 0
} else {
self.bottomViewHeightConstraint.constant = 108
}
self.view.layoutIfNeeded()
}