Reputation: 2334
I'm not sure what I'm doing wrong using NSLayoutConstraint to generate Auto Layout.
I want to put an inner view centered in an outer view using the smaller of the outer view's width and height. Finally, I want to apply a scaling factor.
Here's my code.
NSLayoutConstraint.activate([
inner.centerXAnchor.constraint(equalTo: outer.centerXAnchor),
inner.centerYAnchor.constraint(equalTo: outer.centerYAnchor),
inner.widthAnchor.constraint(equalTo: outer.heightAnchor, multiplier: imageScale),
inner.widthAnchor.constraint(equalTo: outer.widthAnchor, multiplier: imageScale),
inner.heightAnchor.constraint(equalTo: inner.widthAnchor)
])
This works for:
But when width > height I get this:
What am I missing? This is very easy to do using frames:
let innerWidth = min(outer.frame.width, outer.frame.height) * imageScale
let innerHeight = innerWidth
inner.frame = CGRect(x: (outer.frame.width -innerWidth) / 2,
y: (outer.frame.height - innerHeight) / 2,
width: innerWidth, height: innerHeight)
Upvotes: 1
Views: 568
Reputation: 17724
First, it's a bit weird that you are setting the inner.widthAnchor
constraint twice in your code. Set it only once.
Also, you need to select the outer anchor for the inner view's dimensions based on the actual outer view's frame. If the smallest outer dimension is width, then you constrain the width of the inner view to outer.widthAnchor * imageScale
. Otherwise, when the smallest outer dimension is height, you constrain to outer.heightAnchor * imageScale
.
This works for me to get the layout you're looking for (I just created a simple single-view project):
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let inner = UIView()
inner.backgroundColor = .yellow
inner.translatesAutoresizingMaskIntoConstraints = false
let outer = UIView()
outer.backgroundColor = .blue
outer.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(outer)
view.addSubview(inner)
// get these from somewhere, e.g. outerWidth.frame.size
let outerWidth = CGFloat(200)
let outerHeight = CGFloat(400)
let outerAnchor: NSLayoutDimension
if outerWidth >= outerHeight {
outerAnchor = outer.heightAnchor
} else {
outerAnchor = outer.widthAnchor
}
let imageScale = CGFloat(0.5)
NSLayoutConstraint.activate([
outer.widthAnchor.constraint(equalToConstant: outerWidth),
outer.heightAnchor.constraint(equalToConstant: outerHeight),
outer.centerXAnchor.constraint(equalTo: view.centerXAnchor),
outer.centerYAnchor.constraint(equalTo: view.centerYAnchor),
inner.centerXAnchor.constraint(equalTo: outer.centerXAnchor),
inner.centerYAnchor.constraint(equalTo: outer.centerYAnchor),
inner.widthAnchor.constraint(equalTo: outerAnchor, multiplier: imageScale),
inner.heightAnchor.constraint(equalTo: inner.widthAnchor)
])
}
}
Upvotes: 2