Swift Update Constraint

How to update the constant height constraint of a UIView programmatically?

Select the height constraint from the Interface builder and take an outlet of it. So, when you want to change the height of the view you can use the below code.

yourHeightConstraintOutlet.constant = someValue
yourView.layoutIfNeeded()

Method updateConstraints() is an instance method of UIView. It is helpful when you are setting the constraints programmatically. It updates constraints for the view. For more detail click here.

Updating constraints in swift 5

first declare the variable, after set start constraints variable to true and after call a function that active and dis active constraints, try with my example:

under controller class declare a button and a view do you want to move:

let dummyView = UIView()
let button = UIButton(type: .system)

after declare variable to move your view with constraint:

var up: NSLayoutConstraint?
var down: NSLayoutConstraint?

in ViewDiLoad set the view, the button and the constraints like this:

dummyView.backgroundColor = .yellow
dummyView.translatesAutoresizingMaskIntoConstraints = false

button.setTitle("viewDiwn", for: .normal)
button.backgroundColor = .red
button.setTitleColor(.white, for: .normal)
button.titleLabel?.font = .systemFont(ofSize: 16)
button.addTarget(self, action: #selector(handletapButton), for: .touchUpInside)// button action that call handletapButton func
button.translatesAutoresizingMaskIntoConstraints = false

view.addSubview(dummyView)
up = dummyView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
up?.isActive = true // start constraint active
down = dummyView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 100) // constraint to activate for move the view

dummyView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
dummyView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
dummyView.heightAnchor.constraint(equalToConstant: 50).isActive = true

view.addSubview(button)
button.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
button.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
button.heightAnchor.constraint(equalToConstant: 50).isActive = true
button.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true

now write the function to move the view by constraint animation:

@objc func handletapButton() {
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: {
self.up?.isActive = false
self.down?.isActive = true
self.view.layoutIfNeeded()
}, completion: nil)
}

this is the result

Sample Image

Updating Constraints programmatically?

setUpLayout() is adding new constraints every time you call setUpLayout() method. You must save constraint reference and update it next time.

For example.

// class variable 
var bottomConstraint:NSLayoutConstraint? = nil

bottomConstraint = bottomContainer.heightAnchor.constraint(equalToConstant: 500)
bottomConstraint.isActive = true

And later update constraint

bottomConstraint.constant = 100
bottomConstraint.isActive = true

How to update constraints programmatically if I would like to change every time

Since you are using SnapKit, you need to use its .updateConstraints syntax.

This example will toggle .imageConstraint between 50.0 and -50.0 on any touch, and animate the image view:

class SnapVC: UIViewController {

let imageView = UIImageView()

private var imageConstraint = 50.0

override func viewDidLoad() {
super.viewDidLoad()

if let img = UIImage(named: "myImage") {
imageView.image = img
}

view.addSubview(imageView)

imageView.snp.makeConstraints {
$0.width.height.equalTo(48)
$0.centerX.equalToSuperview()
$0.bottom.equalTo(-imageConstraint)
}

}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
imageConstraint *= -1
imageView.snp.updateConstraints {
$0.bottom.equalTo(-imageConstraint)
}
UIView.animate(withDuration: 0.5, animations: {
self.view.layoutIfNeeded()
})
}

}

Update layout constraints programmatically without IBOutlets - Swift

Store the constraint in a variable and change the constant and call layoutIfNeeded when you need it animated.

// Declare this along with the other variables in your class
var constraintVariable: NSLayoutConstraint!

.
.
.

// Where you set your constraints. Store the constraint to be animated in the variable and make it active
// Your other constraints
constraintVariable = sideMenu.leftAnchor.constraint(equalTo: view.leftAnchor, constant: someNegativeValue);
constraintVariable.isActive = true

.
.
.

@objc func slideMenu() {
UIView.animate(withDuration: suitableDuration) {
constraintVariable.constant = requiredValue
view.setNeedsLayout()
view.layoutIfNeeded()
}
}

Modify constraint programmatically Swift

So this is the way I achieved this :

  • Create a constraint programmatically (height in my case) :

    // Drawing height property
    var drawingHeightConstraint: NSLayoutConstraint?
  • Deactivate old constraint and set the new one if needed

Note: heightContraints is an array of NSLayoutConstraint which contains my outlets

        for (index, (drawing, ratio)) in drawingElements.enumerate() {
drawingViews[index].image = UIImage(named: drawing)

// update height constraint if ratio is different than defaut ratio of 1/2
if ratio != 0.5 {
heightConstraints[index].active = false
drawingHeightConstraint = NSLayoutConstraint(item: drawingViews[index], attribute: .Height, relatedBy: .Equal, toItem: drawingView, attribute: .Height, multiplier: CGFloat(ratio), constant: 0)
drawingHeightConstraint!.active = true
}

}
  • Call layoutIfNeeded() right after (note: not sure when to call it)

How do I update constraints after changing UIButton's image

Here's one way to handle it:

Create a struct ButtonSizeConstraints:

struct ButtonSizeConstraints {
let widthConStraint: NSLayoutConstraint
let heightConstraint: NSLayoutConstraint
}

Give your view an array of ButtonSizeConstraints, once for each button. (You could also have separate variables firstButtonSizeConstraints, secondButtonSizeConstraints, etc, but by making it an array you can loop through it.)

In your setupConstraints function, put those constraints into local vars, add them to your array of ButtonSizeConstraints, and activate them outside of the code you posted.

Then, when you load a new image into one or more of your buttons, fetch that button's ButtonSizeConstraints, update that constraint's constant value, and call the parent view's layoutIfNeeded() method.

How to update anchor constraint in swift

Using anchors creates NSLayoutContraints. You need to deactivate the previous ones when you create new ones.

Add this property to your MenuViewController:

var imageLeftConstraint: NSLayoutConstraint?

Set it when you first create the constraint:

imageLeftConstraint = self.imageView.leftAnchor.constraint(equalTo: button.leftAnchor, constant: 0)
imageLeftConstraint?.isActive = true

Then use it to deactivate the previous constraint before adding a new one:

@objc func didSelectedButton(_ button:UIButton) {
imageLeftConstraint?.isActive = false
imageLeftConstraint = self.imageView.leftAnchor.constraint(equalTo: button.leftAnchor)
imageLeftConstraint?.isActive = true
UIView.animate(withDuration: 1, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}

Note: You need to call layoutIfNeeded() on the superView of imageView (aka self.view) because the constraint between button and imageView will be added to their common ancestor (self.view).

UIView does not update new height constraint after action

You need to remove old 1

extension UIView {
func constrainHeight(constant: CGFloat) {
constraints.forEach {
if $0.firstAttribute == .height {
self.removeConstraint($0)
}
}

heightAnchor.constraint(equalToConstant: constant).isActive = true
superView!.layoutIfNeeded()
}
}


Related Topics



Leave a reply



Submit