12

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

5
  • 1
    Create a new constraint with the required constant, deactivate or remove the old and add the new one Commented Mar 14, 2016 at 10:34
  • Is deactivating/deleting a constraint different in terms of processing time ? Commented Mar 14, 2016 at 10:36
  • Probably both are irrelevant compared to rendering the images, but I don't know. I would keep it around if I needed to reactivate it later... Commented Mar 14, 2016 at 10:37
  • @DanieleBernardini : Can you help me about the edited post please ? Commented Mar 14, 2016 at 12:54
  • Can't double check right now. I'll take a look in a few hours. Commented Mar 14, 2016 at 13:12

3 Answers 3

14

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)
Sign up to request clarification or add additional context in comments.

Comments

4

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;

8 Comments

I think you misunderstood what I am trying to achieve. The second picture I put describes what I am trying to get, not an error or mis-manipulation.
@ H4Hugo Yeah, sorry - but the logic is same - use outlets for height constraints and set their values when they must be changed
The problem is I can't use directly the image height. It would be the imageView's height multiplied by the ratio
@H4Hugo... you can set values of constraints directly. Or is there any problem to remove ratio or set value like multiple by 2 if ratio set to 1/2?
@Karaban, Welcome to SO! :) Please, don't create new answers, just edit your original one. And ask any clarifying questions in comments. Creating several answers to one question from one author is not forbidden, but it have to be conceptually different answers, and all of them should be valid.
|
0

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.

2 Comments

The technical reason why you can't change the multiplier: Because the constraints are translated into a complicated system of linear equations, and while the constants can be very easily and quickly modified, changing any of the multipliers requires everything to be recalculated completely.
Seems like this translation happens on the fly anyways, both when the view is rendered, and then again if you programmatically create new constraints and add them. It would be nice to have a future state where we could modify constraints in code, then call some type of [layout] method to force a recalculation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.