Hiding a view inside stackview still keeps constraints active - swift

This code can be copy paste inside a newly created project:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let label = createLabel()
let imageView = createImageView()
let stackView = UIStackView(arrangedSubviews: [imageView, label])
stackView.axis = .vertical
stackView.spacing = 5
view.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (_) in
imageView.isHidden = true
}
}
func createLabel() -> UILabel {
let label = UILabel(frame: .zero)
label.text = "Some Text"
label.setContentHuggingPriority(.required, for: .horizontal)
label.setContentHuggingPriority(.required, for: .vertical)
label.backgroundColor = .green
return label
}
func createImageView() -> UIImageView {
let imageView = UIImageView()
imageView.backgroundColor = .red
imageView.heightAnchor.constraint(equalToConstant: 200).isActive = true
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor).isActive = true
return imageView
}
}
It is a UILabel and a UIImageView inside a UIStackView. When I hide the UIImageView, I see that the UIStackView correctly adapts itselfs to the UILabel's height. However, the UIStackView does not adapts itself to the width of the UILabel.
How can I make the UIStackView resize itself to it's only visible views/UILabel? I made a variabele constraint for the UIImageView's height anchor constant and turning that off when hiding the UIImageView, but than the UILabel disappears for some odd reason.

Add stackview alignment
This property determines how the stack view lays out its arranged
views perpendicularly to its axis. The default value is
UIStackView.Alignment.fill.
stackView.alignment = .leading
Stackview resizes itself to it's only visible UILabel

Try changing the Distribution to Fill Equally in the UIStackView's Attribute Inspector and the Alignment to Fill or to center as you like it to be.

Related

NSLayoutConstraints not cooperating with UIImageView

In my UIView subclass, I have one image view and three labels:
let imageView = UIImageView()
let firstLabel = UILabel()
let secondLabel = UILabel()
let thirdLabel = UILabel()
The image and texts are set by the view controller that uses the view.
I begin to set them up with:
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
addSubview(imageView)
firstLabel.translatesAutoresizingMaskIntoConstraints = false
firstLabel.textAlignment = .center
addSubview(firstLabel)
secondLabel.translatesAutoresizingMaskIntoConstraints = false
secondLabel.textAlignment = .center
addSubview(secondLabel)
thirdLabel.translatesAutoresizingMaskIntoConstraints = false
thirdLabel.textAlignment = .center
addSubview(thirdLabel)
I am trying to constrain these in such a way such that it looks like the following (rough drawing):
Specifically:
thirdLabel is in the center at the bottom
secondLabel is in the center directly above thirdLabel
firstLabel is in the center directly above secondLabel
The size of imageView will vary depending on the size of the view, however it must meet these criteria:
It is in the center directly above firstLabel
It reaches the top
It is a square
So if the height of the view was larger, only the image view would enlarge, the labels would NOT increase height and evenly space out. They would remain at the bottom. So visually, this would be good:
and this would be bad:
An example of what I've tried (one of MANY):
NSLayoutConstraint.activate([
thirdLabel.centerXAnchor.constraint(equalTo: safeAreaLayoutGuide.centerXAnchor),
thirdLabel.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor),
thirdLabel.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor),
thirdLabel.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor),
secondLabel.centerXAnchor.constraint(equalTo: thirdLabel.centerXAnchor),
secondLabel.bottomAnchor.constraint(equalTo: thirdLabel.topAnchor),
secondLabel.leadingAnchor.constraint(equalTo: thirdLabel.leadingAnchor),
secondLabel.trailingAnchor.constraint(equalTo: thirdLabel.trailingAnchor),
firstLabel.centerXAnchor.constraint(equalTo: secondLabel.centerXAnchor),
firstLabel.bottomAnchor.constraint(equalTo: secondLabel.topAnchor),
firstLabel.leadingAnchor.constraint(equalTo: secondLabel.leadingAnchor),
firstLabel.trailingAnchor.constraint(equalTo: secondLabel.trailingAnchor),
imageView.centerXAnchor.constraint(equalTo: firstLabel.centerXAnchor),
imageView.bottomAnchor.constraint(equalTo: firstLabel.topAnchor),
imageView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor),
imageView.widthAnchor.constraint(equalTo: imageView.heightAnchor),
])
I've mixed and matched so many constraints but I cannot achieve the layout in the first image. Not only can I get it working with various heights, I can't even get it to work with ANY height. Sometimes the image view takes up the whole thing and I can't even see the labels (are they underneath the view? behind the image view?). Sometimes the height of the labels are increased. These things occur even though I have constraints that seemingly don't allow this to happen? No breaking of constraint messages appear in the console either.
I believe it may have something to do with sizing, because if I don't set an image (and set a background color for imageView so I can see where it is), it works perfectly. It's only when I actually assign an image to imageView.image do things act up. I've tried resizing the image beforehand, along with setting many variables and constraints not shown in the particular example given above.
Frustrating!
You need to set both Content Compression Resistance and Content Hugging priorities on your labels.
Here is an example custom view class (using mostly your code):
class AJPView: UIView {
let imageView = UIImageView()
let firstLabel = UILabel()
let secondLabel = UILabel()
let thirdLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
addSubview(imageView)
firstLabel.translatesAutoresizingMaskIntoConstraints = false
firstLabel.textAlignment = .center
addSubview(firstLabel)
secondLabel.translatesAutoresizingMaskIntoConstraints = false
secondLabel.textAlignment = .center
addSubview(secondLabel)
thirdLabel.translatesAutoresizingMaskIntoConstraints = false
thirdLabel.textAlignment = .center
addSubview(thirdLabel)
NSLayoutConstraint.activate([
thirdLabel.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor),
thirdLabel.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor),
thirdLabel.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor),
secondLabel.bottomAnchor.constraint(equalTo: thirdLabel.topAnchor),
secondLabel.leadingAnchor.constraint(equalTo: thirdLabel.leadingAnchor),
secondLabel.trailingAnchor.constraint(equalTo: thirdLabel.trailingAnchor),
firstLabel.bottomAnchor.constraint(equalTo: secondLabel.topAnchor),
firstLabel.leadingAnchor.constraint(equalTo: secondLabel.leadingAnchor),
firstLabel.trailingAnchor.constraint(equalTo: secondLabel.trailingAnchor),
imageView.centerXAnchor.constraint(equalTo: firstLabel.centerXAnchor),
imageView.bottomAnchor.constraint(equalTo: firstLabel.topAnchor),
imageView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor),
imageView.widthAnchor.constraint(equalTo: imageView.heightAnchor),
// you've given the labels leading and trailing constraints,
// so you don't need these
//thirdLabel.centerXAnchor.constraint(equalTo: safeAreaLayoutGuide.centerXAnchor),
//secondLabel.centerXAnchor.constraint(equalTo: thirdLabel.centerXAnchor),
//firstLabel.centerXAnchor.constraint(equalTo: secondLabel.centerXAnchor),
])
// prevent labels from being compressed or stretched vertically
[firstLabel, secondLabel, thirdLabel].forEach {
$0.setContentCompressionResistancePriority(.required, for: .vertical)
$0.setContentHuggingPriority(.required, for: .vertical)
}
// let's give the subviews background colors
// so we can easily see the frames
let clrs: [UIColor] = [
.systemYellow,
.green,
.cyan,
.yellow
]
for (v, c) in zip([imageView, firstLabel, secondLabel, thirdLabel], clrs) {
v.backgroundColor = c
}
}
}
and a demo view controller:
class ViewController: UIViewController {
var heightConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
let testView = AJPView()
testView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(testView)
let g = view.safeAreaLayoutGuide
heightConstraint = testView.heightAnchor.constraint(equalToConstant: 120.0)
NSLayoutConstraint.activate([
testView.widthAnchor.constraint(equalToConstant: 300.0),
testView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
testView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
// activate height anchor
heightConstraint,
])
testView.firstLabel.text = "First"
testView.secondLabel.text = "Second"
testView.thirdLabel.text = "Third"
if let img = UIImage(named: "myImage") {
testView.imageView.image = img
} else {
if let img = UIImage(systemName: "person.circle.fill") {
testView.imageView.image = img
}
}
// so we can see the frame of the view
testView.layer.borderWidth = 1
testView.layer.borderColor = UIColor.red.cgColor
// add grow / shrink buttons
let stack = UIStackView()
stack.translatesAutoresizingMaskIntoConstraints = false
stack.spacing = 20
stack.distribution = .fillEqually
["Taller", "Shorter"].forEach {
let b = UIButton(type: .system)
b.backgroundColor = .yellow
b.setTitle($0, for: [])
b.addTarget(self, action: #selector(btnTapped(_:)), for: .touchUpInside)
stack.addArrangedSubview(b)
}
view.addSubview(stack)
NSLayoutConstraint.activate([
stack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
stack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
stack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
])
}
#objc func btnTapped(_ sender: UIButton) -> Void {
var h = heightConstraint.constant
if sender.currentTitle == "Taller" {
h += 10
} else {
h -= 10
}
heightConstraint.constant = h
}
}
The output looks like this (the custom view is outlined in red):
you can tap the "Taller" / "Shorter" buttons to make the custom view grow or shrink (by 10-pts each tap) to see the changes:
Note that the view will eventually get too tall for the 1:1 ratio image view to fit horizontally:

iOS how to create a UIView border with label on top of that

I have to add label on top of UIView border, how do I achieve that using beizer path by drawing only part of the border on view
This can be realized by implementing a BorderLabelView where a contentView and a label is added. To the contentView a textField is added which is positioned vertically centered to its parent.
The label is positioned relatively to the top of the parent but moved up by a negative constant value.
An extra contentView is used (instead of the BorderLabelView itself) to set the border with rounded corners, so that masksToBounds can be set without masking the part of the label that sticks up a little bit.
For the label some leading and trailing space is needed. That is why UILabel is subclassed so that intrinsicContentSize can be reset.
This is a working example implementation:
import UIKit
class PaddedLabel: UILabel {
override var intrinsicContentSize: CGSize {
CGSize(width: super.intrinsicContentSize.width + 20, height: super.intrinsicContentSize.height)
}
}
class BorderLabelView: UIView {
convenience init(labelName: String, textContent: String) {
self.init()
let contentView = UIView()
contentView.backgroundColor = .white
contentView.layer.borderWidth = 0.5
contentView.layer.borderColor = UIColor.lightGray.cgColor
contentView.layer.cornerRadius = 10;
contentView.layer.masksToBounds = true;
let textField = UITextField()
textField.textColor = .black
textField.font = UIFont.systemFont(ofSize: 22.0)
textField.text = textContent
contentView.addSubview(textField)
textField.translatesAutoresizingMaskIntoConstraints = false
textField.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 25).isActive = true
textField.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
addSubview(contentView)
contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.topAnchor.constraint(equalTo: topAnchor).isActive = true
contentView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
contentView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
let label = PaddedLabel()
label.text = labelName
label.backgroundColor = .white
label.textColor = UIColor.lightGray
label.textAlignment = .center
addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.topAnchor.constraint(equalTo: topAnchor, constant: -10).isActive = true
label.leftAnchor.constraint(equalTo: leftAnchor, constant: 15).isActive = true
}
}
The view can be used by calling the initializer
BorderLabelView(labelName: "User name", textContent: "Sanjay SK")
This is an example implementation for a UIViewController:
import UIKit
class BorderLabelController: UIViewController {
override func viewDidLoad() {
view.backgroundColor = .white
let borderLabelView = BorderLabelView(labelName: "User name", textContent: "Sanjay SK")
view.addSubview(borderLabelView)
borderLabelView.translatesAutoresizingMaskIntoConstraints = false
borderLabelView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
borderLabelView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
borderLabelView.heightAnchor.constraint(equalToConstant: 100).isActive = true
borderLabelView.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.size.width - 40).isActive = true
}
}
Create a border and rounded UIView.. Inside that view you can add label or UITextField whose text is "Sanjay SK" with respect to given sample image
Give that view border color , border width and corer radious.. then take a UILabel with background color white and add it over that bordered UIView ... will give you same look and feel ... hope it will help you

Resize superview according to label's font size and image's aspect ratio

This is an auto-layout related question. I've containerView which has two subviews: imageView and label. I want to let the fontsize of the label determine the size of the containerView according to the aspect ratio of imageView.
When the font size increases, the containerView and the imageView should get bigger maintaining the aspect ratio and keeping the label centered with some padding as shown in the image below.
And I want to achieve it programmatically.
Any help will be much appreciated
You can accomplish this by:
constrain image view to all 4 sides of container
constrain label centered in container
constrain image view to 16:9 ratio
constrain image view's height to label's height + desired "padding"
Here's an example, including buttons to increase / decrease the font size:
class WalterViewController: UIViewController {
let theContainerView: UIView = {
let v = UIView()
v.backgroundColor = .blue
return v
}()
let theImageView: UIImageView = {
let v = UIImageView()
v.backgroundColor = .red
v.contentMode = .scaleToFill
return v
}()
let theLabel: UILabel = {
let v = UILabel()
v.backgroundColor = .yellow
v.textAlignment = .center
v.text = "TEST"
// content vertical hugging REQUIRED !!!
v.setContentHuggingPriority(.required, for: .vertical)
return v
}()
let btnUp: UIButton = {
let b = UIButton(type: .system)
b.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
b.setTitle("Increase", for: .normal)
return b
}()
let btnDn: UIButton = {
let b = UIButton(type: .system)
b.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
b.setTitle("Decrease", for: .normal)
return b
}()
let btnStack: UIStackView = {
let v = UIStackView()
v.axis = .horizontal
v.spacing = 12
v.distribution = .fillEqually
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
// we'll be using constraints
[theContainerView, theImageView, theLabel, btnUp, btnDn, btnStack].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
}
// add buttons to the stack
btnStack.addArrangedSubview(btnUp)
btnStack.addArrangedSubview(btnDn)
// add imageView and label to container
theContainerView.addSubview(theImageView)
theContainerView.addSubview(theLabel)
// add button stack and container view to view
view.addSubview(btnStack)
view.addSubview(theContainerView)
// respect safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// horizontal button stack 20-points from top, 40-points on each side
btnStack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
btnStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
btnStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
// container view centered in view safeArea
theContainerView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
theContainerView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
// constrain image view to its superView (container view)
// 8-pts on all 4 sides
theImageView.topAnchor.constraint(equalTo: theContainerView.topAnchor, constant: 8.0),
theImageView.leadingAnchor.constraint(equalTo: theContainerView.leadingAnchor, constant: 8.0),
theImageView.trailingAnchor.constraint(equalTo: theContainerView.trailingAnchor, constant: -8.0),
theImageView.bottomAnchor.constraint(equalTo: theContainerView.bottomAnchor, constant: -8.0),
// label is centered in its superView (container view)
theLabel.centerXAnchor.constraint(equalTo: theContainerView.centerXAnchor),
theLabel.centerYAnchor.constraint(equalTo: theContainerView.centerYAnchor),
// constrain imageView to 16:9 ratio
theImageView.widthAnchor.constraint(equalTo: theImageView.heightAnchor, multiplier: 16.0 / 9.0),
// constrain imageView's height to label's height +40
// will result in 20-pts on top and bottom
theImageView.heightAnchor.constraint(equalTo: theLabel.heightAnchor, constant: 40.0),
])
// load an image
if let img = UIImage(named: "bkg640x360") {
theImageView.image = img
}
// add targets to buttons to increase / decrease the label's font size
btnUp.addTarget(self, action: #selector(increaseTapped(_:)), for: .touchUpInside)
btnDn.addTarget(self, action: #selector(decreaseTapped(_:)), for: .touchUpInside)
}
#objc func increaseTapped(_ sender: Any?) -> Void {
theLabel.font = theLabel.font.withSize(theLabel.font.pointSize + 1.0)
}
#objc func decreaseTapped(_ sender: Any?) -> Void {
theLabel.font = theLabel.font.withSize(theLabel.font.pointSize - 1.0)
}
}
How it looks on launch (container view is centered in root view):
and, after tapping Increase a bunch of times:

How to center multiple buttons horizontally in Swift?

I am creating multiple buttons programmatically. For an example, if I am creating two buttons with defined spacing among buttons, I want to center these two buttons horizontally in the view controller. How can I do this with swift?
You can use UIStackView with horizontal axis property, add the buttons inside the UIStackView and add constraints on stackView to center in the view.
Here is the simple example of centering two buttons equally at the bottom of the screen, 8 points above safeAreaLayout guides.
class ViewController: UIViewController {
lazy var button1: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = .red
button.setTitle("Button1", for: .normal)
return button
}()
lazy var button2: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = .blue
button.setTitle("Button2", for: .normal)
return button
}()
lazy var horizontalStackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [button1, button2])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .horizontal
stackView.distribution = .fillEqually
stackView.spacing = 8
return stackView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(horizontalStackView)
NSLayoutConstraint.activate([
horizontalStackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -8),
horizontalStackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8),
horizontalStackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -8),
horizontalStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
horizontalStackView.heightAnchor.constraint(equalToConstant: 50)
])
}
}
here is the view:
Play around this code in playground and change as per your requirements.
UIStackView is what you're looking for.
Example
Declare btn1, btn2 first, then put them into a UIStackView.
lazy var horizontalStackView: UIStackView = {
let sv = UIStackView(arrangedSubviews: [
btn1,
btn2
])
sv.axis = .horizontal
sv.spacing = 8
return sv
}()
override func viewDidLoad() {
view.addSubview(horizontalStackView)
// Then set up its constraint of horizontalStackView
horizontalStackView.translatesAutoresizingMaskIntoConstraints = false
horizontalStackView.topAnchor...
}
At last, you just need to anchor the horizontalStackView like a normal UIView to where you want.

UIView Mask Is Causing View To Move Positions (AutoLayout)

In my app, I have a UILabel, which I am using to mask a UIView. I am using AutoLayout throughout the app, and am finding that when setting the mask of my label, its position suddenly changes.
Here is my code when adding my label;
// Label
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Hello!"
label.font = UIFont.systemFont(ofSize: 50.0)
label.textColor = UIColor.white
view.addSubview(label)
// Constraints
label.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
This produces the result. When adding the mask, however, via the following code;
// Mask
let mask = UIView()
mask.translatesAutoresizingMaskIntoConstraints = false
mask.backgroundColor = UIColor.blue
mask.mask = label
view.addSubview(mask)
// Constraints
mask.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
mask.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
mask.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
mask.heightAnchor.constraint(equalTo: self.view.heightAnchor).isActive = true
My label ends up repositioning itself, and I am seeking to have the text stay in position at the perfect center.
You cannot use Auto Layout on the view that is used as a mask. That view it lives outside the normal view hierarchy. You do not add it to the view hierarchy by calling addSubview(_:), you only add it as a mask by setting it as the mask property of another view.
Because of that you have to set the label's frame directly to center your label. You also have to set it again everytime the frame of your masked view changed (e.g. if the user rotates the device). Because of that you have to set the label's frame in viewDidLayoutSubviews()
I tried to make it work by just setting the label's center to the view's center, but that does not work. Somehow the label does not get displayed. I could make it work by explicitly setting the labels size to its intrinsicContentSize. I guess this is because the label is used as a masked and never part of the view hierarchy.
Here is a working example. I took the liberty to change the naming from mask to maskedView to avoid confusion with the mask property ;-)
class ViewController: UIViewController {
var label = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
// Label
label.text = "Hello!"
label.font = UIFont.systemFont(ofSize: 50.0)
label.textColor = UIColor.white
// Mask
let maskedView = UIView()
maskedView.translatesAutoresizingMaskIntoConstraints = false
maskedView.backgroundColor = UIColor.blue
maskedView.mask = label
view.addSubview(maskedView)
// Constraints
maskedView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
maskedView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
maskedView.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
maskedView.heightAnchor.constraint(equalTo: self.view.heightAnchor).isActive = true
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let labelHeight = label.intrinsicContentSize.height
let labelWidth = label.intrinsicContentSize.width
label.frame = CGRect(
x: view.center.x - labelWidth / 2,
y: view.center.y - labelHeight / 2,
width: labelWidth,
height: labelHeight
)
}
}
You could make the code inside viewDidLayoutSubviews() a bit shorter by setting label.textAlignment = .center
Then this is enough:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
label.frame = view.frame
}