Make UILabel Constraint to display full width - ios

I'm struggling to implement to make my uilabel to stretch from the left side to right side (Full Width), I can do it easily in storyboard but I have a part on my app that needs to display a uilabel progmatically.
Here's my code:
textLabel.backgroundColor = UIColor.grayColor()
textLabel.text = StringsLabel.NOINTERNET
textLabel.textAlignment = .Center
textLabel.font = UIFont.boldSystemFontOfSize(24.0)
textLabel.translatesAutoresizingMaskIntoConstraints = false
centerView.addSubview(textLabel)
let centreXTopLabel:NSLayoutConstraint = NSLayoutConstraint(item: textLabel, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: centerView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0);
centerView.addConstraint(centreXTopLabel)
Here's the screenshot of what i've got:

Pin it to the leading and trailing of the view at 0 points:
let leading = NSLayoutConstraint(item: textLabel, attribute: .Leading, relatedBy: .Equal, toItem: centerView, attribute: .Leading, multiplier: 1, constant: 0)
let trailing = NSLayoutConstraint(item: textLabel, attribute: .Trailing, relatedBy: .Equal, toItem: centerView, attribute: .Trailing, multiplier: 1, constant: 0)
NSLayoutConstraint.activateConstraints([leading, trailing])
Note that this will result in an ambiguous layout — you need to add a constraint that positions the label vertically.

Try this..
let views = ["textLabel" : textLabel]
let formatString = "|-[textLabel]-|"
let constraints = NSLayoutConstraint.constraintsWithVisualFormat(formatString, options:.AlignAllTop , metrics: nil, views: views)
NSLayoutConstraint.activateConstraints(constraints)

Related

Adding programmatically label with relative constraint issue

I've an UITableView with some cells, in the first cell I would like to add multiple UILabel. That's the code I am using inside a function in UITableViewCell sub class (called in cellForRowAt):
...
let constantTop = 16
for (index,optional) in optionals.enumerated(){
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "\(optional.name)"
label.tag = 10010132
label.font = CocoFonts.semibold(size: 15)
label.textColor = CocoColors.FedericoMalagoni.textVeryDarkBlue
self.contentView.addSubview(label)
let constant:CGFloat = CGFloat(constantTop * (index + 1))
print(constant)
let horizontalConstraint = NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self.contentView, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 16)
let verticalConstraint = NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: self.contentView, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 16)
let height = NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20)
let top = NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.lblInfo, attribute: NSLayoutAttribute.bottomMargin, multiplier: 1, constant: constant)
let bottom = NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.contentView, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: constant)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, top, bottom, height])
}
self.contentView.setNeedsUpdateConstraints()
self.contentView.setNeedsLayout()
self.contentView.layoutIfNeeded()
...
Now,
The labels are over the edge of the cell like this:
The gray separator divide the cell.
Essentially the height of the cell is not updated.
It would be more clear if you could share full implementation of cellForRowAt.
I faced similar issue where cell contents were overlapping. I was adding custom view to the cell as subview.
This happens because Table view re uses its cells. So one solution is to remove old label from the cell before you add new.
for content in cell.contentView.subviews {
content.removeFromSuperview()
}

NSLayoutConstraint style for VFL

"V:|[v(>=height)]-0.0#highPriority-|"
What will be the constraint (NSLayoutConstraint style) for above VFL.
Perhaps its considering view height with greaterThanEqual & bottom constraint with UILayoutPriority.defaultHigh.
Something i used -
let heightConstraint = NSLayoutConstraint(item: self.view!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.greaterThanOrEqual, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 0)
let bottomConstraint = NSLayoutConstraint(item: self.view!, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 0)
bottomConstraint.priority = .defaultHigh
NSLayoutConstraint.activate([heightConstraint,bottomConstraint])
Initial Set up for Answer:
let parentView = self.view!
let childView = UIView()
childView.backgroundColor = UIColor.lightGray
childView.translatesAutoresizingMaskIntoConstraints = false
parentView.addSubview(childView)
For given VFL:
"V:|[v(>=height)]-0.0#highPriority-|"
1. VFL Implementation:
let height: CGFloat = 100
let priority: Int = 1000
//VFL (for vertical positioning and height of childView
parentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v(>=\(height))]-0.0#\(priority)-|",
options: [],
metrics: nil,
views: ["v" : childView]))
2. NSLayoutConstraint Implementation:
The above VFL's NSLayoutConstraint equivalent is:
let height: CGFloat = 100
//VFL Equivalent: "V:|[v]"
let topConstraint = NSLayoutConstraint(item: childView,
attribute: .top,
relatedBy: .equal,
toItem: parentView,
attribute: .top,
multiplier: 1,
constant: 0)
//VFL Equivalent: "[v(>=height)]"
let heightConstraint = NSLayoutConstraint(item: childView,
attribute: .height,
relatedBy: .greaterThanOrEqual,
toItem: nil,
attribute: .notAnAttribute,
multiplier: 1,
constant: height)
//VFL Equivalent: "[v]|" or "[v]-0.0-|"
let bottomConstraint = NSLayoutConstraint(item: childView,
attribute: .bottom,
relatedBy: .equal,
toItem: parentView,
attribute: .bottom,
multiplier: 1,
constant: 0)
//Adding VFL Equivalent: #priority
bottomConstraint.priority = .defaultHigh
childView.addConstraint(heightConstraint)
parentView.addConstraint(topConstraint)
parentView.addConstraint(bottomConstraint)
NOTE: The given VFL in your question only provides the childViews y position and height.
For width, add the constraints accordingly.
VFL Example for width would be:
parentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v(100)]",
options: [],
metrics: nil,
views: ["v" : childView]))
Ref:
Apple's Autolayout Guide on VFL

Constraints were ignored when trying to implement constraints programmatically

I'm trying to center a logoImage horizontally & vertically by setting constraints but when tested, It was displayed on (x:0, y:0).
Any idea how to fix this?
Thanks
var movieView : UIView?
let logoImage = UIImageView(image: #imageLiteral(resourceName: "my_logo"))
// This function runs in viewWillAppear
internal func setupIntroMovie() {
movieView = UIView(frame: view.frame)
view.addSubview(movieView!)
view.addSubview(logoImage)
let horizontalConstraint = NSLayoutConstraint(item: logoImage,
attribute: .centerX,
relatedBy: .equal,
toItem: view,
attribute: .centerX,
multiplier: 1,
constant: 0)
let verticalConstraint = NSLayoutConstraint(item: logoImage,
attribute: .centerY,
relatedBy: .equal,
toItem: view,
attribute: .centerY,
multiplier: 1,
constant: 0)
view.addConstraints([horizontalConstraint,
verticalConstraint])
updateViewConstraints()
}
You need to set logoImage.translatesAutoresizingMaskIntoConstraints = false as it determines whether the view’s autoresizing mask is translated into Auto Layout constraints.
internal func setupIntroMovie() {
movieView = UIView(frame: view.frame)
view.addSubview(movieView!)
view.addSubview(logoImage)
let horizontalConstraint = NSLayoutConstraint(item: logoImage,
attribute: .centerX,
relatedBy: .equal,
toItem: view,
attribute: .centerX,
multiplier: 1,
constant: 0)
let verticalConstraint = NSLayoutConstraint(item: logoImage,
attribute: .centerY,
relatedBy: .equal,
toItem: view,
attribute: .centerY,
multiplier: 1,
constant: 0)
// Update
logoImage.translatesAutoresizingMaskIntoConstraints = false
view.addConstraints([horizontalConstraint,
verticalConstraint])
updateViewConstraints()
}
If this property’s value is true, the system creates a set of
constraints that duplicate the behavior specified by the view’s
autoresizing mask. This also lets you modify the view’s size and
location using the view’s frame , bounds , or center properties,
allowing you to create a static, frame-based layout within Auto
Layout.

Auto layout not set properly when give equal width constrains to buttons

I see many solution and applied auto layout constrains but still i am not getting desired solution.
Current Result:
Constrains given to all button:
View Hierarchy:
Assuming that what do you want is letting the 3 buttons equal each others and filling the width of screen using the Interface Builder (with no code, i.e: not programmatically), this is a solution:
you don't need to add them in views. just follow these steps:
let's start with this:
note that the buttons don't have any constraints -yet-, just add them to the to the bottom of the view (or where ever you want to display them, for this solution, I will display them in bottom of the screen). Make sure that the 3 of them have the same size.
Adding constraints to the orange button:
add the following constraints:
leading, bottom space, and equal height.
Adding constraints to the blue button:
add the following constraints:
trailing, bottom space and equal height.
Adding constraints to the cyan button:
ctrl + drag from the cyan button to the orange button and add the following constraints: horizontal spacing and center vertically.
ctrl + drag from the cyan button to the blue button and add the following constraints: horizontal spacing.
bottom space and equal height.
So far so good, we are almost done!
Now, select the 3 buttons and add the following constraint: equal widths.
Your buttons should look like this:
Now, all you have to do is select each of the two horizontal spacing constraints and set their constants to 0 -from the size inspector-:
AND there you go:
I hope this helped, Cheers Up.
Sorry for solution in code.. .Swift 3.0:
let button1 = UIButton()
let button2 = UIButton()
let button3 = UIButton()
let buttons = [button1, button2, button3]
button1.backgroundColor = .red
button2.backgroundColor = .blue
button3.backgroundColor = .green
buttons.forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
buttons.forEach {
let cnt1 = NSLayoutConstraint(item: $0, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1, constant: 0)
let cnt2 = NSLayoutConstraint(item: $0, attribute: .height, relatedBy: .equal, toItem: view, attribute: .height, multiplier: 0.2, constant: 0)
view.addConstraints([cnt1, cnt2])
}
let cnt1 = NSLayoutConstraint(item: button1, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0)
let cnt2 = NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: button3, attribute: .trailing, multiplier: 1, constant: 0)
let cnt3 = NSLayoutConstraint(item: button2, attribute: .width, relatedBy: .equal, toItem: button1, attribute: .width, multiplier: 1, constant: 0)
let cnt4 = NSLayoutConstraint(item: button3, attribute: .width, relatedBy: .equal, toItem: button2, attribute: .width, multiplier: 1, constant: 0)
let cnt5 = NSLayoutConstraint(item: button2, attribute: .leading, relatedBy: .equal, toItem: button1, attribute: .trailing, multiplier: 1, constant: 0)
let cnt6 = NSLayoutConstraint(item: button3, attribute: .leading, relatedBy: .equal, toItem: button2, attribute: .trailing, multiplier: 1, constant: 0)
view.addConstraints([cnt1, cnt2, cnt3, cnt4, cnt5, cnt6])
Are you trying to lay out three buttons horizontally that have equal height and width? I think you can achieve this without using UIViews. I set constraints like as follows.
This is a simulator screenshot.

Autolayout - UIView does not resize correctly to subview's size

I'm trying to programmatically create a UIView with a UILabel as a subview using autolayout.
Constraints
I used the following constraints on view:
CenterX of view to fastAttacksContainerView (superview).
Top constraint of constant 8 to superview.
Then created a label which is a subview of view and added constraints of constant 8 for Top, Bottom, Left, and Right to view.
Problem
The view only resizes to the frame of the label and does not account for the 4 constraints of constant 8 on all 4 sides. Which causes the label to be displayed partially outside the view.
let view = UIView()
view.backgroundColor = pokemon.secondaryColor
let label = UILabel()
fastAttacksContainerView.addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.text = fa
let gest = UITapGestureRecognizer(target: self, action: #selector(self.selectFastAttack))
view.addGestureRecognizer(gest)
fastAttackButtons.append(view)
fastAttackLables.append(label)
let top = NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal, toItem: fastAttacksContainerView, attribute: .Top, multiplier: 1, constant: 8)
let centerX = NSLayoutConstraint(item: view, attribute: .CenterX, relatedBy: .Equal, toItem: fastAttacksContainerView, attribute: .CenterX, multiplier: 1, constant: 0)
let labLeft = NSLayoutConstraint(item: label, attribute: .Left, relatedBy: .Equal, toItem: view, attribute: .Left, multiplier: 1, constant: 8)
let labTop = NSLayoutConstraint(item: label, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1, constant: 8)
let labRigth = NSLayoutConstraint(item: label, attribute: .Right, relatedBy: .Equal, toItem: view, attribute: .Right, multiplier: 1, constant: 8)
let labBottom = NSLayoutConstraint(item: label, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1, constant: 8)
view.addConstraints([labLeft, labTop, labRigth, labBottom])
fastAttacksContainerView.addConstraints([top, centerX])
Output
view has ambiguous height.
You should add constraint for height of view or distance from it to bottom of fastAttacksContainerView.
I managed to fix this problem by making a similar setup on storyboard and copying the constraints in.
Things that I changed:
Used Leading and Trailing instead of Left and Right layout attributes.
For the labLeft and labRight constraints, I interchanged item and toItem. (This seems like a bug to me. Can anyone verify, please?)
Code change:
let labLeft = NSLayoutConstraint(item: label, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1, constant: 8)
let labTop = NSLayoutConstraint(item: label, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1, constant: 8)
let labRigth = NSLayoutConstraint(item: view, attribute: .Trailing, relatedBy: .Equal, toItem: label, attribute: .Trailing, multiplier: 1, constant: 8)
let labBottom = NSLayoutConstraint(item: view, attribute: .Bottom, relatedBy: .Equal, toItem: label, attribute: .Bottom, multiplier: 1, constant: 8)

Resources