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
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 NSLayoutContraint
s. 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
How to Connect Localhost (With Invalid Certificate) Using Alamofire
Subclass Nsapplication in Swift
Swift Anyobject Is Not Convertible to String/Int
Alternate Approach to Inheritance for Swift Structs
Reversing the Order of a String Value
How to Detect a 'Click' Gesture in Swiftui Tvos
Converting .M4A File to .Aiff Using Audioconverter Swift
How to Convert a Swift String to Cfstring
Get Just the Date (No Time) from Uidatepicker
Filter by Multiple Array Conditions
Binary Operator '+' Cannot Be Applied to Two 'T' Operands
Rxswift/Rxcocoa: Prevent Uitextfield from Having More Than ... Characters
Scenekit - Scntext Centering Incorrectly
How to Get User Input in Apple's Swift Language in a Command Line Tool
How to Save and Load Arworldmap in Swiftui App