I don't know if this is a Swift bug or if I made a mistake, but there is a weird behaviour.
I have a UILabel and a UISwitch inside a horizontal UIStackView, but the trailing of the UISwitch is cut off because it's sticking out the stackView (see images).
Does anyone have a similar problem or is it just me? And if it's a Swift bug, is there a workaround?
Here is my code:
private lazy var alreadyInPlaceStackView: UIStackView = {
UIStackView(arrangedSubviews: [alreadyInPlaceLabel, alreadyInPlaceSwitch],
axis: .horizontal,
spacing: Constants.horizontalPadding,
alignment: .fill,
distribution: .fill)
}()
private lazy var alreadyInPlaceLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.conference.background.on_background
label.numberOfLines = 1
label.font = UIFont.label
label.text = "report.intubation.already-in-place.title".localized()
return label
}()
private lazy var alreadyInPlaceSwitch: UISwitch = {
let view = UISwitch()
view.onTintColor = UIColor.conference.highlight.primary
view.addTarget(self,
action: #selector(switchValueDidChange(_:)),
for: .valueChanged)
view.setContentCompressionResistancePriority(.required, for: .horizontal)
return view
}()
Constraints:
alreadyInPlaceStackView.leadingAnchor.constraint(equalTo: switchStackViewContainerView.leadingAnchor),
alreadyInPlaceStackView.trailingAnchor.constraint(equalTo: switchStackViewContainerView.trailingAnchor),
alreadyInPlaceStackView.topAnchor.constraint(equalTo: videoLaryngoscopeStackView.bottomAnchor, constant: Constants.verticalPadding),
alreadyInPlaceStackView.bottomAnchor.constraint(equalTo: switchStackViewContainerView.bottomAnchor),
switchStackViewContainerView.leadingAnchor.constraint(equalTo: detailsContainer.leadingAnchor),
switchStackViewContainerView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
switchStackViewContainerView.topAnchor.constraint(equalTo: difficultIntubationStackView.bottomAnchor, constant: Constants.verticalPadding),
switchStackViewContainerView.bottomAnchor.constraint(equalTo: detailsContainer.bottomAnchor),
Thanks!
Decided to do a little more investigation on this... I was wrong about the "trailing" aspect.
Let's look at a simple example -- we'll add a blue
UIViewand aUISwitch, and constrain the width of the blue view to the width of the switch:Here's what we get:
and, if we tap, we see this in the Debug Console:
The switch is 2-points wider than the blue view!!!
So, let's try setting the blue view's width constraint after the switch has been fully laid-out.
We comment-out the width constraint:
and on tap, we'll set it:
Looks like this before tap (because blueView has no width):
and after tap:
and console output is again:
Equal is apparently not always Equal !!!
Let's look at a common use-case -- we will embed a label and a switch in a view (or, as in your example, a stack view) for "Option" toggles:
and we get this:
On tap we'll clear the backgrounds, AND we'll turn on
clipsToBoundsfor the blue view:This is what I would call, clearly, a bug.Worth noting... if we evaluate the
intrinsicContentSizeof the switch:Console shows:
Edit
Based on Matt's answer and explanation of the
alignmentRectInsetsofUISwitch, I'll retract my claim of this being a "bug" and instead accept that it is intended layout behavior.I'll leave my example code and images here though (as an exercise in futility).