Move UI element using constraints via code

Viewed 84

I am trying to make a simple animation using constraints. When the button is pressed, the following occurs:

First step

Second step

I created two variables for height and boolean

    var isCollectionOpen = false
    var collectionHeightConstraint = NSLayoutConstraint()

Set limits for the entire user interface through code and in the same place brought the height of the collection to a variable

// ...
        btcView.collectionView.heightAnchor.constraint(equalToConstant: collectionHeightConstraint.constant),
// ...

And I'm trying to change the constraints on pressing the button. But nothing happens. What is my problem?


    func example() {
        collectionHeightConstraint.constant = isCollectionOpen ? (view.frame.width / 4) : 0
        isCollectionOpen = !isCollectionOpen
    }
2 Answers

This is simple enough. It seems you are trying to make a constraint equal to another constraint and then just changing the other constant.

This

btcView.collectionView.heightAnchor.constraint(equalToConstant: collectionHeightConstraint.constant)

just reads the current value of collectionHeightConstraint. It doesn't make the constraint magically keep the same value as collectionHeightConstraint.

Instead:

var collectionHeightConstraint: NSLayoutConstraint?

and store reference to the created constraint:

collectionHeightConstraint = btcView.collectionView.heightAnchor.constraint(equalToConstant: 0)

Then simply change it:

collectionHeightConstraint.constant = isCollectionOpen ? (view.frame.width / 4) : 0

However, this is not the best solution. I would personally create two constraints with different priorities:

let hiddenConstraint = btcView.collectionView.heightAnchor.constraint(equalToConstant: 0)
hiddenConstraint.priority = UILayoutPriority.required - 1
self.visibleConstraint = btcView.collectionView.heightAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1 / 4)

And then just toggle visibleConstraint.isActive = false to hide the view and visibleConstraint.isActive = true to hide the view.

With the help of the answer @Sulthan

I did the following:

  1. Created two variables
    var isCollectionOpen = false
    var visibleConstraint: NSLayoutConstraint?
  1. In the constraint store
    let hiddenConstraint = btcView.collectionView.heightAnchor.constraint(equalToConstant: 0)
    hiddenConstraint.priority = UILayoutPriority.required - 1
    visibleConstraint = btcView.collectionView.heightAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1 / 4)

// ...
    btcView.collectionView.heightAnchor.constraint(equalToConstant: hiddenConstraint.constant),
// ...
  1. Where I get data into a collection
    if !isCollectionOpen {
        visibleConstraint?.isActive = true
        isCollectionOpen = true
    } else {
        visibleConstraint?.isActive = false
        isCollectionOpen = false
        return // Don't download data again
    }
Related