当视图大小不同时,如何通过编程方式设置约束?

时间:2018-12-23 19:53:50

标签: swift4 nslayoutconstraint xcode10 ios11.4

使用Xcode 10,iOS 11.4 +,Swift 4

我正在浏览一系列UIViewController, 每个都被放置到ContainerView中。

enter image description here

基于推送的VC,我将在主控制器中隐藏/显示“顶”或“底”视图(以灰色显示),而ContainerView始终位于中间(浅蓝色)。

我想做的是设置约束,以便在显示/隐藏顶部或底部视图时适当调整ContainerView的大小。

例如,当显示“主菜单”时,ContainerView应该填充整个“主容器”视图(顶视图和底视图将被隐藏)

显示“ Item1”时,将显示“顶”视图,而“底”视图将隐藏。因此,ContainerView应该在左侧,右侧和底部填充“主容器”视图,但ContainerView的顶部应限制在“顶部”视图的底部。

当显示“ Item5”时,还将显示“顶部”和“底部”视图。 因此,ContainerView应该向左,向右填充“主容器”视图,并限制在“顶视图”底部和“底视图”顶部(如“主容器”中所示)

我尝试使用这样的代码填充整个主视图:

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]无法同时满足约束。     以下列表中的约束中至少有一个是   你不要。

这是情节提要中的另一个屏幕截图: enter image description here

以下是下载我的示例项目的链接: https://gitlab.com/whoit/containerviews

如何正确修改约束以完成此任务?

2 个答案:

答案 0 :(得分:1)

正如我在评论中提到的那样,您应该使用UIStackView来控制顶视图/底视图的可见性。

您将需要一个具有以下属性的UIStackView

  • 轴:垂直
  • 对齐方式:填充
  • 分发:填充
  • 间距:根据您的需要

堆栈视图将分别包含顶视图容器视图底视图作为其子视图。

您需要将此堆栈视图的所有侧面(前导,尾随,顶部和底部)固定到其父视图(视图控制器的视图)。而且,由于您需要为顶视图和底视图设置一些高度限制,因此可以根据需要提供它们。


因此,基本上,您的堆栈视图现在可以在隐藏任何子视图时调整其子视图的大小。您只需要执行:

theSubViewNeedsTobeHidden.isHidden = true

我为您制作了一个有效的演示,可以here找到。

答案 1 :(得分:0)

问题

1)您一直在添加新的约束,因为每次调用它们时,这些行都会创建新的约束:

ContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0)

2)首先,MainContainerView完全不受约束

解决方案

我建议以下内容:

  • 在情节提要中添加这四个约束
  • 为顶视图和底视图的高度约束创建IBOutlets。
  • 将其中的constant设置为0(隐藏它们时)
  • (可选),确保您仍然可以通过设置它们的alpha来淡入/淡出它们,然后将高度常数添加到完成块中。

注意: 布局时仍会考虑隐藏视图(alpha = 0isHidden = true)。这意味着,当视图被隐藏时,您的约束仍然有效。但是要使它们在布局中也看起来像隐藏的,则必须将它们的高度constant设置为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()
}