H4Hugo
H4Hugo

Reputation: 2650

Modify constraint programmatically Swift

I have the following view controller in my storyboard :

storyboard_mainVC

It will always have 6 image views that are, by default, equal in widths and heights. Each image view is constrained to the superview with : "equal heights" and a multiplier of 1/2.

However, before I load images inside, I read a property that gives me the desired height for an image (width will never be modified).

So my interface (at runtime) can look like this :

second_interface

I think I need to modify the multiplier constant but it's read-only.

I saw posts saying that we can update the constant property of the constraint but it's in points, I need it to work on every device.

Now what would you recommend ? Should I remove the constraint and add a new one ? If I don't remove it and try to apply a new height constraint, will it be removed automatically for me ?

Do I have to use pods like snapkit to do the job ?

Thanks for your help.

EDIT

Here is the code I tried, but did not succeeded :

        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
                let newHeightConstraint = NSLayoutConstraint(item: drawingViews[index], attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.Height, multiplier: ratio, constant: 0)
                drawingViews[index].addConstraint(newHeightConstraint)
                self.view.layoutIfNeeded()
            }
        }

Am I doing it wrong ? I am unsure about the new height constraint though

Upvotes: 12

Views: 38345

Answers (3)

H4Hugo
H4Hugo

Reputation: 2650

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)

Upvotes: 14

FreeNickname
FreeNickname

Reputation: 7764

You can not change the multiplier for reasons unknown to me (some kind of Apple's implementation detail probably). You can remove a constraint and create a new one, however. You have to remove the old constraint, because it will not be removed automatically, and you'll get a conflict. Alternatively, you could create the first constraint (with the 0.5 multiplier) with lower priority. This way you could keep it (autolayout would just ignore it), but I don't think it is a way to go, since why would you need that unnecessary constraint? Just delete it. As for third-party layout engines and libraries – unfortunately, I can't give you any advice here.

Upvotes: 0

Karaban
Karaban

Reputation: 151

The constraints constants are related to the content of the constrained element. That why you're getting such screen. The easiest way - create image with clear color and set it by default. After downloading completed just set new image for your imageView

Or you can set IBOutlet for your height constraint - and change it value for different situations i.e.

if(download.completed)
ibHeightOutlet.constant = imageView.frame.size.height;
else
ibHeightOutlet.constant = initialImageViewHeght.frame.size.height;

Upvotes: 4

Related Questions