How to Change Label Constraints During Runtime

How to change label constraints during runtime?

Select the header label, and one of the lower labels, and add a new vertical space constraint reflecting the gap between them. Next, remove the header label Top space to container constraint. Maybe you already have this (can't quite see from the screen grab). If you do, that's good.

Now, create two height constraints for each lower label. IBOutlet those to your class.

Then, hide those two lower labels whenever you need to by setting each height constraint's constant to 0.f.

That will render them invisible and lower the header label above so that it is now vertically centered Y in the container.

Will go through the steps once more (was too long for a comment!). Sequence matters with IB as first you must add a new constraint before you can delete the old one. Temporarily you will have one superfluous constraint. It's because IB won't allow ambiguity. So, first add the new vertical space constraint. That will define the Y position of the upper label. Then, remove the superfluous vertical space to container constraint from the upper label. Now that label will be Y positioned using the vertical space relative to the lower labels. Next, add the height constraints for each lower label and link to the class with an IBOutlet. One other thing, actually you will need the lower labels to be constrained to the container with a bottom space constraint. When their height is reduced to zero, they will disappear, and the upper label will move lower to assume the Y center position.

To revert, just set the constant back to the original value.

This is a much better approach than adding/removing constraints, which is a heavyweight operation. Note that you may wish to add the two lower labels to a "container" view, so that they can be shown/hidden as one. Also, it would tidy the code as you really want the vertical space to be between your upper label, and both lower labels rather than just one.

See also my answer AutoLayout with hidden UIViews?

what scenarios of layout design needs Dynamic height label and a text field next to each other?

Even though your question is a little unclear, let's see if this helps explain things...

Suppose we start with 2 labels - LabelA (green) and LabelB (cyan):

Sample Image

LabelB is constrained 20-pts below LabelA... as we add text to LabelA, it will grow in height, "pushing" LabelB down and keeping the 20-pts vertical spacing:

Sample Image

Sample Image

Sample Image

All of that is pretty simple, and it's exactly what we expect to happen.

But, suppose we want LabelB to start at 100-pts from the top of the view (the safe-area), and only move down if LabelA gets tall enough?

If we add a Top constraint to LabelB, that will stretch LabelA:

Sample Image

Or, it will compress LabelA:

Sample Image

In both cases because LabelB Top cannot be both 100-pts from the view Top AND 20-pts from LabelA Bottom at the same time.

So, let's change LabelB Top to at least 20-pts from LabelA bottom, by setting it to >=, and, we'll change the LabelB Top constraint to a priority of less-than-required. In this example, we'll use Default High (750).

What we've done is told auto-layout to break the 100-pt Top constraint if needed. So, if LabelA is short, LabelB can be at 100-pts, but if LabelA gets tall, keep LabelB 20-pts below LabelA and break the 100-pt Top constraint:

Sample Image

Sample Image

Sample Image

Sample Image

So, it's not so much the order in which the constraints are evaluated, as it is the logical ability for auto-layout to satisfy all the constraints.


Edit

To try and explain the specific example from Apple...

Let's start with a minimum set of constraints, where the fonts are:

Label - 30pt
Field - 14pt

Sample Image

The Name Label is 40-pts from the Top, and the Name Text Field is constrained to the FirstBaseline of the label.

Now let's change the fonts to this:

Label - 20pt
Field - 30pt

so the Field is taller than the Label, here's what we get:

Sample Image

The Top of the label is still 40-pts from the Top, but the field has been moved up (to maintain the baseline alignment) and the Top of the field is now only (about) 25-pts from the Top.

The goal is to keep the Top of tallest element at 40-pts. With only these two vertical constraints, as we can see, we failed.

So, let's reset the fonts to:

Label - 30pt
Field - 14pt

and add the additional constraints with specified Priorities:

Sample Image

The positioning is identical to the first example, but... if we again change the fonts to:

Label - 20pt
Field - 30pt

this is the result:

Sample Image

The Top of the field is at 40-pts, and the Top of the label has moved down (to maintain the baseline alignment).

And... we've accomplished our goal!


Edit 2

To try to clarify with "plain language"...

The Baseline constraint will control the relative vertical alignment of the two elements. As we change the font size of one, it will make that element "taller" (or "shorter") and the other element will move vertically to keep the baselines aligned.

We've added a required constraint of top >= 40 to each element. That tells auto-layout "don't let either element be closer than 40-pts from the top."

We've added a constraint of top = 40 to each element, with Priority: 249. That tells auto-layout "try to put the top of each element at 40-pts... if you can't (because the baseline alignment is pulling it down), then go ahead and break that top constraint."

How to implement constraints for 1 image between 2 label for storyboard file

you probably need UIStackView with distribution set to Fill Equally

StackView

How to set UILabel only width and height and constraints programmatically

To create label with height and width constraints here is the constraints...And don't forget to add label in to view with addSubview method

UILabel *Label = [[UILabel alloc] init];
[Label setTranslatesAutoresizingMaskIntoConstraints:NO];

[self.view addSubview:Label];

// Width constraint
[Label addConstraint:[NSLayoutConstraint constraintWithItem:Label
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute: NSLayoutAttributeNotAnAttribute
multiplier:1
constant:200]];

// Height constraint
[Label addConstraint:[NSLayoutConstraint constraintWithItem:Label
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute: NSLayoutAttributeNotAnAttribute
multiplier:1
constant:21]];

Swift 4:

label.translatesAutoresizingMaskIntoConstraints = false
label.addConstraint(NSLayoutConstraint(item: label, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 21))
label.addConstraint(NSLayoutConstraint(item: label, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200))

And In Swift

 Label.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addSubview(Label)

Label.addConstraint(NSLayoutConstraint(item: Label, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 21))
Label.addConstraint(NSLayoutConstraint(item: Label, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 200))

Check this link for more detail

UPDATE
As you update your question, here is my updated answer...

UILabel *Label1 = [[UILabel alloc] init];
[Label1 setTranslatesAutoresizingMaskIntoConstraints:NO];
UILabel *Label2 = [[UILabel alloc] init];
[Label2 setTranslatesAutoresizingMaskIntoConstraints:NO];

Label1.text = @"Label1";
Label1.backgroundColor = [UIColor blueColor];
Label2.text = @"Label2";
Label2.backgroundColor = [UIColor redColor];

[self.view addSubview:Label1];
[self.view addSubview:Label2];

// Width constraint
[Label1 addConstraint:[NSLayoutConstraint constraintWithItem:Label1
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute: NSLayoutAttributeNotAnAttribute
multiplier:1
constant:280]];

// Height constraint
[Label1 addConstraint:[NSLayoutConstraint constraintWithItem:Label1
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute: NSLayoutAttributeNotAnAttribute
multiplier:1
constant:21]];

// CenterX constraint
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:Label1
attribute: NSLayoutAttributeCenterX
multiplier:1
constant:0]];
// Top constraint
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:Label1
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.topLayoutGuide
attribute: NSLayoutAttributeBottom
multiplier:1
constant:40]];

// label2
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:Label1
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:Label2
attribute: NSLayoutAttributeLeading
multiplier:1
constant:0]];
// label2.Height = label1.Height
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:Label1
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:Label2
attribute: NSLayoutAttributeHeight
multiplier:1
constant:0]];
// label2.width = label1.width
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:Label1
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:Label2
attribute: NSLayoutAttributeWidth
multiplier:1
constant:0]];

// label2.Top
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:Label2
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:Label1
attribute: NSLayoutAttributeBottom
multiplier:1
constant:34]];

Result Screen

Sample Image

How to set fixed width for UILabel to let other UIViews make constraint to it?

Fix the width of both the labels and use minimum font size. Now put the constraints on the slider relative to the labels. Now the slider will be fixed. Just the font size of labels will change accordingly.

Label next to a label with variable length

A little tricky, but not too tricky...

What you need to do is set multiple, similar constraints and use a combination of Content Compression Resistance Priority and Constraint Priority on the different elements.

Take a look at this:

Sample Image

  • We embed Left Label in a scroll view.
  • We constrain the width of the scroll view to the width of the label, but with a Priority of 750. That will allow the scroll view to expand (and contract) with the label until it can't expand anymore.
  • We add constraints to Right Label... leading to the scroll view, and trailing to the right edge of the view, with the trailing set to >= 20 and the compression resistance set to 1000. That allows the label to "stick" to the scroll view as it expands / contracts, but will not allow it to go past the right edge, nor compress past its own content width.
  • The rest of the constraints are pretty standard.

And we get:

Sample Image

I whipped up a simple example that will let you change the text with button taps to see it in action:

Sample Image

Here's the class:

class ScrollingLabelViewController: UIViewController {

@IBOutlet var leftLabel: UILabel!
@IBOutlet var rightLabel: UILabel!

override func viewDidLoad() {
super.viewDidLoad()

}

@IBAction func leftTap(_ sender: Any) {
if let btn = sender as? UIButton {

let t = btn.currentTitle

switch t {

case "Short Text":
leftLabel.text = "Example Name"

case "Medium Text":
leftLabel.text = "Example Longer Name"

case "Long Text":
fallthrough

default:
leftLabel.text = "Example Name that is long enough that it will need to scroll."

}
}
}

@IBAction func rightTap(_ sender: Any) {
if let btn = sender as? UIButton {

let t = btn.currentTitle

switch t {

case "Short Text":
rightLabel.text = "(6)"

case "Medium Text":
rightLabel.text = "(255)"

case "Long Text":
fallthrough

default:
rightLabel.text = "(38,872)"

}
}
}

}

And the Storyboard source:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="itP-Si-dAD">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Scrolling Label View Controller-->
<scene sceneID="2HK-o9-I65">
<objects>
<viewController id="itP-Si-dAD" customClass="ScrollingLabelViewController" customModule="XC10SWScratch" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="C9r-ad-Wv2">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Rs3-TC-hFe">
<rect key="frame" x="20" y="60" width="114.5" height="20.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="1000" text="Example Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3jj-Oq-9XF">
<rect key="frame" x="0.0" y="0.0" width="114.5" height="20.5"/>
<color key="backgroundColor" red="0.0" green="0.99143940210000003" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="3jj-Oq-9XF" secondAttribute="bottom" id="7EF-mm-DaK"/>
<constraint firstAttribute="width" secondItem="3jj-Oq-9XF" secondAttribute="width" priority="750" id="ZtX-rP-Lme"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="12" id="ZyU-il-ReF"/>
<constraint firstItem="3jj-Oq-9XF" firstAttribute="top" secondItem="Rs3-TC-hFe" secondAttribute="top" id="ml2-6X-bBl"/>
<constraint firstItem="3jj-Oq-9XF" firstAttribute="leading" secondItem="Rs3-TC-hFe" secondAttribute="leading" id="r4q-LE-OQ5"/>
<constraint firstAttribute="trailing" secondItem="3jj-Oq-9XF" secondAttribute="trailing" id="t9q-89-BOF"/>
<constraint firstAttribute="height" secondItem="3jj-Oq-9XF" secondAttribute="height" id="xDp-np-bFT"/>
</constraints>
</scrollView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="1000" text="(6)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZCj-c5-IzQ">
<rect key="frame" x="142.5" y="60" width="23" height="20.5"/>
<color key="backgroundColor" red="0.0" green="0.99143940210000003" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" spacing="47" translatesAutoresizingMaskIntoConstraints="NO" id="0v3-eY-MTM">
<rect key="frame" x="44" y="160.5" width="287" height="164.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="18" translatesAutoresizingMaskIntoConstraints="NO" id="nou-P9-haw">
<rect key="frame" x="0.0" y="0.0" width="120" height="164.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Left Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Jgc-gS-1Oz">
<rect key="frame" x="0.0" y="0.0" width="120" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mPG-zF-zdi">
<rect key="frame" x="0.0" y="38.5" width="120" height="30"/>
<color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="Short Text"/>
<connections>
<action selector="leftTap:" destination="itP-Si-dAD" eventType="touchUpInside" id="z5m-yd-ACM"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xiv-Uc-UPL">
<rect key="frame" x="0.0" y="86.5" width="120" height="30"/>
<color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="Medium Text"/>
<connections>
<action selector="leftTap:" destination="itP-Si-dAD" eventType="touchUpInside" id="hCp-75-WVo"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LQD-gc-Pv1">
<rect key="frame" x="0.0" y="134.5" width="120" height="30"/>
<color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="Long Text"/>
<connections>
<action selector="leftTap:" destination="itP-Si-dAD" eventType="touchUpInside" id="fWI-cl-wGZ"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="width" constant="120" id="Mvo-co-QSU"/>
</constraints>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="18" translatesAutoresizingMaskIntoConstraints="NO" id="usT-YQ-P4a">
<rect key="frame" x="167" y="0.0" width="120" height="164.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Right Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WXA-Lo-BaW">
<rect key="frame" x="0.0" y="0.0" width="120" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="UXZ-r3-dw1">
<rect key="frame" x="0.0" y="38.5" width="120" height="30"/>
<color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="Short Text"/>
<connections>
<action selector="rightTap:" destination="itP-Si-dAD" eventType="touchUpInside" id="1e8-Dh-iHD"/>
</connections>
</button>


Related Topics



Leave a reply



Submit