change heightAnchor of higher size then current size is not working

1.3k Views Asked by At

I have one view whose height is 50

myView.heightAnchor.constraint(equalToConstant: 50).isActive = true

Now what I want to do is when I click button (buton1), I want to change its height to 20. So I make below and it's working fine.

myView.heightAnchor.constraint(equalToConstant: 20).isActive = true

Now in myView I have another button (button2), when I click on it, I want to go back to previous height of 50, but it's not working.

myView.heightAnchor.constraint(equalToConstant: 50).isActive = true

Problem is here. Now the view is not re-sizing like when click on button1.

Note :

When I click on button1 & use below code, re-size also not work.

myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

What I found is if I try to re-size to higher size of current size, it don't work.

Any idea why view is not re-sizing?


Edit 1

Even I wrote below after updating height anchor but still not working.

myView.layoutIfNeeded()
self.view.layoutIfNeeded()

Edit 2

Working Option 1

When click on button1, I do below and works.

myView.heightAnchor.constraint(equalToConstant: 40).isActive = true

When click on button2, I do below and works.

myView.heightAnchor.constraint(equalToConstant: 30).isActive = true

Not Working Option 2

When click on button1, I do below and works.

myView.heightAnchor.constraint(equalToConstant: 40).isActive = true

When click on button2, I do below and NOT WORK.

myView.heightAnchor.constraint(equalToConstant: 50).isActive = true

So what I found is I change height higher then previous, it don't work

3

There are 3 best solutions below

4
Oscar Apeland On BEST ANSWER

At the moment, you are creating a new rule about the view's height every time. iOS doesn't understand how to make a view both 10, 20 and 30 pixels high, so it will do the lowest one. To avoid creating conflicting heights, you need to have one height rule and change that one's constant when needed. Here's a somewhat contained example.

class CoolView: UIViewController {

    lazy var myView = UIView()
    lazy var myViewHeightAnchor = myView.heightAnchor.constraint(equalToConstant: 10)

    override func viewDidLoad() {
        super.viewDidLoad()

        myView.backgroundColor = .black//livesMatters
        myView.translatesAutoresizingMaskIntoConstraints = false

        view.addSubview(myView)
        NSLayoutConstraint.activate([
            myView.topAnchor.constraint(equalTo: view.topAnchor),
            myView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            myView.widthAnchor.constraint(equalToConstant: 10),
            myViewHeightAnchor
        ])
    }

    @objc func someButtonTapped() {
        myViewHeightAnchor.constant = 20
        view.layoutIfNeeded()
    }

    @objc func anotherButtonTapped() {
        myViewHeightAnchor.constant = 30
        view.layoutIfNeeded()
    }
}
7
Frankenstein On

You should keep the reference to the constraint and change the constant value and then call layoutIfNeeded method to achieve this. Here's how:

// First
let heightConstraint = myView.heightAnchor.constraint(equalToConstant: 50)
heightConstraint.isActive = true
// Then to change
heightConstraint.constant = 20
myView.layoutIfNeeded()

As requested I'm adding playground sample here (try this out on Xcode-playground):

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {
    var heightConstraint: NSLayoutConstraint?
    override func viewDidLoad() {
        super.viewDidLoad()

        let sampleView = UIView()
        sampleView.backgroundColor = .green
        sampleView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(sampleView)

        heightConstraint = sampleView.heightAnchor.constraint(equalToConstant: 50)

        let button = UIButton(type: .contactAdd)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.addTarget(self, action: #selector(handleAction), for: .touchUpInside)

        view.addSubview(button)
        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            sampleView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            sampleView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            heightConstraint!,
            sampleView.widthAnchor.constraint(equalToConstant: 200)
        ])
    }

    @objc func handleAction() {
        heightConstraint?.constant = heightConstraint?.constant == 50 ? 30 : 50
    }
}

PlaygroundPage.current.setLiveView(ViewController())

Here you can see how updating the heightConstraint changes the height of the sampleView when the button is clicked. I'm toggling between 50 and 30 points in height here.

0
Fahim Parkar On

So short story,

I was adding below line every time I want to update height which is wrong.

myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

With this, what it do is take the least height and set that. Ex If I set height 3 times as 100, 20, 80, it will take 20 as the height even I run with 80.

To avoid this, we have to add a variable for the height constraint

var heightConstraint : NSLayoutConstraint?

Now while adding constraints to view, add as below.

heightConstraint = mainCVView.heightAnchor.constraint(equalToConstant: 50)
heightConstraint!.isActive = true

Now whenever you want to update height do it as below instead of adding constraint again.

heightConstraint?.constant = 0
heightConstraint?.isActive = true
myView.layoutIfNeeded()

This is most important step and not to add constraint the way I was adding in question

So whenever you want to update just update constant as show above. That's it.