I'm creating a view programmatically and need to set constraints between two labels. I recently just discovered NSLayoutAnchor and feel it would be a good choice to use it but I'm unsure how to create constraints between two different things (ie labels, imageViews, etc). I know a general setup will look something like this:
let codedLabel:UILabel = UILabel()
codedLabel.frame = CGRect(x: 100, y: 100, width: 200, height: 200)
codedLabel.textAlignment = .center
codedLabel.text = alertText
codedLabel.numberOfLines=1
codedLabel.textColor=UIColor.red
codedLabel.font=UIFont.systemFont(ofSize: 22)
codedLabel.backgroundColor=UIColor.lightGray
self.contentView.addSubview(codedLabel)
codedLabel.translatesAutoresizingMaskIntoConstraints = false
codedLabel.heightAnchor.constraint(equalToConstant: 200).isActive = true
codedLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
codedLabel.centerXAnchor.constraint(equalTo: codedLabel.superview!.centerXAnchor).isActive = true
codedLabel.centerYAnchor.constraint(equalTo: codedLabel.superview!.centerYAnchor).isActive = true
How would you set up constraints in between two labels?
Let's say you have two
UIViews
you wish to lay out horizontally in one of two ways:View #1 is 20 points from the leading edge of the superview's margin or safe area and View #2 is another 20 points from view #1. (Think of a left-justified row of buttons.)
Both views are to be centered, with equal spacing before/between/after each view. (Think of two buttons spaced equally apart and centered.)
For example #1 the code would be:
Comment #1: Note that you do not need to give each view a frame, but you do need to set the auto-resizing mask to false. This is a mistake many new coders forget.
Comment #2: All
UIViewController
main views have alayoutMarginGuide
that yield standard margins both vertically and horizontally (and in iOS 11, particularly for iPhone X, there is a newsafeAreaLayoutGuide
for vertical alignment). I've set the leading edge ofview1
to be the leading edge of themargin
with an additional constant of 20 points from it.Comment #3: Just like I related
view1
to themargin
, I'm relatingview2
toview1, but this time the leading edge of
view2is 20 points from the
view1` trailing edge.Comment #4: The last thing you need to do for horizontal placement is to give each view a width. In this case I wanted both to be 100 points.
Example #2 pretty much uses the same code as example #1, so I'll note the key differences only:
Comment #1: In iOS 9 Apple introduced the concept of
UILayoutGuides
. Before this, to create "spacers" you had to actually create an invisibleUIView
and add it as a subview (with all the overhead associated with it). Layout guides "act" like views but do not have that overhead.Comment #2: The horizontal sequence if "margin...spacer1...view1...spacer2...view2...spacer3...margin". Note that I'm not using any constants, as I wish to let the layout engine give equal spacing.
Comment #3: While I am giving width values for both views, I am not with the spacers. Instead, I am declaring their widths to be equal.
Please note that I've only worked with horizontal constraints. For auto layout to work, you also need to declare vertical constraints too. Most of the concepts are the same... instead of leading/trailing, centerX, and width anchors you have top/bottom, centerY, and height ones. BUT! Starting with iOS 11 you now have a
safeAreaLayoutGuide
that you should be using instead oflayoutMarginsGuide
. This only applies to vertical! That's why I separated things. Here's the code I use to work with vertical alignment:Now you have
layoutGuideTop
andlayoutGuideBottom
that should work regardless of what iOS version is running.