When How to Activate/Deactivate Layout Constraints

How to deactivate my constraints?

I hope the following code will help you,

1) declare the global variables

var searchTextViewPortraitWidthConstraint: NSLayoutConstraint?
var searchTextViewLandscapeWidthConstraint: NSLayoutConstraint?
let searchTextView = UITextView()

2) viewDidLoad()

    override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

setupSearchTextView()
let isPortrait = UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)
if isPortrait {
searchTextViewPortraitWidthConstraint = searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.7)
searchTextViewLandscapeWidthConstraint = searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.1)

searchTextViewPortraitWidthConstraint?.isActive = true
} else {
searchTextViewLandscapeWidthConstraint = searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.1)
searchTextViewPortraitWidthConstraint = searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.7)
searchTextViewLandscapeWidthConstraint?.isActive = true
}
}

configure textview

func setupSearchTextView(){
searchTextView.frame = CGRect(x: <#T##CGFloat#>, y: <#T##CGFloat#>, width: <#T##CGFloat#>, height: <#T##CGFloat#>)
/*
.
.
.
.
.
.*/
}

3) to activate or deactivate the width constraint based on device orientation use the any one of the below approach (i.e, viewWillLayoutSubviews() or viewDidLayoutSubviews()).

override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let isPortrait = UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)
if isPortrait{
searchTextViewPortraitWidthConstraint?.isActive = true
searchTextViewLandscapeWidthConstraint?.isActive = false
}else{
searchTextViewPortraitWidthConstraint?.isActive = false
searchTextViewLandscapeWidthConstraint?.isActive = true
}
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let isPortrait = UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)
if isPortrait{
searchTextViewPortraitWidthConstraint?.isActive = true
searchTextViewLandscapeWidthConstraint?.isActive = false
}else{
searchTextViewPortraitWidthConstraint?.isActive = false
searchTextViewLandscapeWidthConstraint?.isActive = true
}
}

Activate/deactivate autolayout NSLayoutConstraints

The solution was that I had to change the priority of both constraints.
Set the constraint you want to use by default to a priority of anything lower then 1000. For instance, 750.
Set the priority of the other constraint to 250. (In Storyboard).

Once you want the second constraint to replace the first one, simply change the priority of the second constraint from 250 to anything higher than 750, and it will magically work.

Activating and Deactivating Constraints Not Updating View Frame

change this

self.view.removeConstraint(constraint1)

to

parentView.removeConstraint(constraint1)
self.view.layoutIfNeeded()

This constraint need to be removed from the parent view of both the label and the button which contains that constraint

Constraint doesn't get deactivated

Couple issues...

1 - many iPhone models only have wC hR (portrait) and wC hC (landscape) size classes. So, if you're checking for the .horizontalSizeClass on those devices it will always be .compact. You likely want to be checking the .verticalSizeClass

2 - the way you have your code, you are creating NEW constraints every time you call addConstrainsToCenterView(). You're not activating / deactivating existing constraints.

Take a look at this:

class MyViewController: UIViewController {

var heightSizeClass = UIUserInterfaceSizeClass.unspecified

var centeredView : UIView = {
let view = UIView()
view.backgroundColor = UIColor.systemGreen
return view
}()

// constraints to activate/deactivate
var compactAnchor: NSLayoutConstraint!
var regularAnchor: NSLayoutConstraint!

override func viewDidLoad() {
super.viewDidLoad()

self.view.addSubview(centeredView)
centeredView.translatesAutoresizingMaskIntoConstraints = false

// centeredView is Always centerX and centerY
centeredView.centerXAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerXAnchor).isActive = true
centeredView.centerYAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerYAnchor).isActive = true

// for a square (1:1 ratio) view, it doesn't matter whether we set
// height == width
// or
// width == height
// so we can set this Active all the time
centeredView.heightAnchor.constraint(equalTo: centeredView.widthAnchor).isActive = true

// create constraints to activate / deactivate

// for regular height, set the width to 4/5ths the width of the view
regularAnchor = centeredView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 4/5)

// for compact height, set the height to 4/5ths the height of the view
compactAnchor = centeredView.heightAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.heightAnchor, multiplier: 4/5)

}

override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()

// use .verticalSizeClass
heightSizeClass = self.traitCollection.verticalSizeClass

updateCenterViewConstraints()
}

func updateCenterViewConstraints() {

if heightSizeClass == .compact {
// if height is compact
regularAnchor.isActive = false
compactAnchor.isActive = true
}
else{
// height is regular
compactAnchor.isActive = false
regularAnchor.isActive = true
}
}
}

With that approach, we create two vars for the constraints we want to activate/deactivate:

    // constraints to activate/deactivate
var compactAnchor: NSLayoutConstraint!
var regularAnchor: NSLayoutConstraint!

Then, in viewDidLoad(), we add centeredView to the view, set its "non-changing" constraints - centerX, centerY, aspect-ratio - and create the two activate/deactivate constraints.

When we change the size class, we only have to deal with the two var constraints.

NSLayoutConstraint activate/deactivate

You can try to change the priority of constraint.
For example:

constraint.priority = 0;    // it's turn off
constraint.priority = 1000; // it's turn on

Enable + Disable Auto-Layout Constraints

Aha!

Constraints become nil (and thus can't be reactivated), once their active property is set to false. Making them strong references (thanks, Caleb, for clearing up the nomenclature) preserves them so they can be activated and deactivated as desired.

Programmatically disable auto-layout constraint

When developing for iOS 8.0 or later, just use isActive property of NSLayoutConstraint after creating your IBOutlet.

UPDATED

  • to have strong reference to the outlet per below suggestion, thank you @rob mayoff.
  • to use .isActive instead of .active with Swift 4 per below suggestion, thank you @Mohit Singh.

your cell would have the following outlet:

@IBOutlet var photoBottomConstraint: NSLayoutConstraint!

and you would access the constraint in willDisplayCell like:

myCell.photoBottomConstraint.isActive = false

and when you need it again:

myCell.photoBottomConstraint.isActive = true


Related Topics



Leave a reply



Submit