【问题标题】:Swift - Programmatically Change ConstraintsSwift - 以编程方式更改约束
【发布时间】:2019-01-18 10:13:22
【问题描述】:

我正在尝试通过以编程方式操作约束来“显示”和“隐藏”集合视图。

我的应用是用代码编写的,没有使用故事板或@IBOutlets。

第一次按下按钮时,集合视图按预期正确显示。

我第二次按下按钮时,集合视图只是停留在原地,并没有“隐藏”。

openMenu 代码中的打印语句确认正在调用每个约束块。即:我收到“打开”和“关闭”的控制台消息。

创建集合视图没有问题,只是以编程方式设置约束不会关闭菜单。

我的代码如下...

override func viewDidLoad() {
    super.viewDidLoad()

    navigationController?.isNavigationBarHidden = false

    view.backgroundColor = .white

    view.addSubview(bgImageView)

    view.addSubview(myListCV)
}

lazy var myListCV: UICollectionView = {

    let myListLayout = UICollectionViewFlowLayout()
    myListLayout.itemSize = CGSize(width: 200, height: 40)
    myListLayout.minimumLineSpacing = 1
    myListLayout.sectionHeadersPinToVisibleBounds = true

    let myListView = UICollectionView(frame: .zero, collectionViewLayout: myListLayout)
    myListView.translatesAutoresizingMaskIntoConstraints = false
    myListView.delegate = self
    myListView.dataSource = self

    myListView.bounces = false
    myListView.alwaysBounceVertical = false
    myListView.showsVerticalScrollIndicator = true
    myListView.backgroundColor = UIColor(r: 203, g: 203, b: 203)

    return myListView
}()

var menuShowing = false

func openMenu() {

    if (menuShowing) {
        print("closed")
        myListCV.leftAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        myListCV.topAnchor.constraint(equalTo: view.topAnchor, constant: 64).isActive = true
        myListCV.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        myListCV.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

    } else {
        print("open")
        myListCV.leftAnchor.constraint(equalTo: view.rightAnchor, constant: -200).isActive = true
        myListCV.topAnchor.constraint(equalTo: view.topAnchor, constant: 64).isActive = true
        myListCV.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        myListCV.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    }

    menuShowing = !menuShowing
}

【问题讨论】:

  • 使用视图调试器!
  • 您应该激活/停用约束,而不是简单地将事物设置为isActive = true。考虑一下 - rightAnchor 约束被设置 两次,这取决于 if 语句!怎么合乎逻辑? (a) 将您的约束分组到数组中并激活/停用它们,或者 (b)通过变量名声明您希望更改的约束并然后 i> 在你的 if 语句中改变它们。
  • @matt 感谢您的意见。如果通过“使用视图调试器!”你的意思是放置断点并单步执行代码,我已经做到了。我可以看到我正在设置两个左锚约束,这可能会阻止集合视图关闭。我相信“if”语句只会根据条件设置所要求的内容。您能否提供任何可以帮助我解决此问题的 cmets?
  • @dfd 谢谢,我将研究通过变量声明,只更改我需要“隐藏”集合视图的变量。约束的常数一旦改变,是否应该立即生效?即:无需重新加载视图。
  • 视图调试器显示您的视图。还有你的限制。它揭示了约束问题。它会立即解释一切

标签: swift uicollectionview constraints


【解决方案1】:

上述代码的问题在于,每次用户打开或关闭该部分时,您都会不断设置约束,因此根据用户执行此操作的次数,您最终会得到数百个不存在的约束需要。

您应该做的是设置默认状态的约束,我假设在这种情况下关闭,并将您希望更改的约束存储在属性中。然后你可以简单地调整这个约束的常数来显示/隐藏你的菜单。

例如

private var myListCVLeftConstraint: NSLayoutConstraint?

override func viewDidLoad() {
    super.viewDidLoad()

    navigationController?.isNavigationBarHidden = false

    view.backgroundColor = .white

    view.addSubview(bgImageView)

    self.configMyListCV()
}

lazy var myListCV: UICollectionView = {

    let myListLayout = UICollectionViewFlowLayout()
    myListLayout.itemSize = CGSize(width: 200, height: 40)
    myListLayout.minimumLineSpacing = 1
    myListLayout.sectionHeadersPinToVisibleBounds = true

    let myListView = UICollectionView(frame: .zero, collectionViewLayout: myListLayout)
    myListView.translatesAutoresizingMaskIntoConstraints = false
    myListView.delegate = self
    myListView.dataSource = self

    myListView.bounces = false
    myListView.alwaysBounceVertical = false
    myListView.showsVerticalScrollIndicator = true
    myListView.backgroundColor = UIColor(r: 203, g: 203, b: 203)

    return myListView
}()

var menuShowing = false

private func configMyListCV() -> Void {

    view.addSubview(myListCV)

    self.myListCV.topAnchor.constraint(equalTo: view.topAnchor, constant: 64).isActive = true
    self.myListCV.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
    self.myListCV.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

    self.myListCVLeftConstraint = myListCV.leftAnchor.constraint(equalTo: view.rightAnchor)
    self.myListCVLeftConstraint.isActive = true
}

func openMenu() {

    if (menuShowing) {

        self.myListCVLeftConstraint?.constant = 0.0

    } else {

        self.myListCVLeftConstraint?.constant = -200.0

    }

    menuShowing = !menuShowing
}

这对于这个简单的用户案例很有效;但是,如果您将来做更深入的事情,我建议您在视图上设置多个约束,并根据需要简单地禁用/启用所需的约束。

【讨论】:

  • 非常感谢您的意见。这就像一个魅力,非常感谢。如果我想做更复杂的事情,我会注意到您关于启用/禁用约束的建议。
  • 太棒了。节省了我很多时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 2014-01-22
  • 1970-01-01
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多