I'm trying to make used of preservesSuperviewLayoutMargins
through a nested view hierarchy but hitting a lot of issues with UIKit and wondering what I am doing wrong (or whether this is a genuine bug).
I'm trying to lay out a handful of views (some by the side of each other, some above each other) like so:
// Various combinations here will create different visual results (it will either work or won't)
let i1 = ImageView()
//let i1 = LabelView()
let i2 = ImageView()
//let i2 = LabelView()
let i3 = ImageView()
//let i3 = LabelView()
let view = LeftRight(left: i1, right: TopBottom(top: i2, bottom: i3))
//let view = LeftRight(left: TopBottom(top: i2, bottom: i3), right: i1)
With some layout's I can get it to work, shown below. You can see that the images on the right are correctly indented against the green view, which is in turn correctly indented against the white view.
But with others I am struggling:
Running code similar to this in an app I can get a complete lockup and memory runaway.
The indenting is done using layoutMargins
like this:
let masterView = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
masterView.translatesAutoresizingMaskIntoConstraints = false
masterView.layoutMargins = UIEdgeInsets(top: 5.0, left: 5.0, bottom: 5.0, right: 5.0)
let subView = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
subView.translatesAutoresizingMaskIntoConstraints = false
subView.layoutMargins = UIEdgeInsets(top: 5.0, left: 5.0, bottom: 5.0, right: 5.0)
Here's a sample of the image layout from a playground. The full playground project can be found here and can easily be loaded up and ran in XCode to see what I mean.
class ImageView: UIView {
init() {
super.init(frame: CGRect(x: 0, y: 0, width: 1000, height: 1000))
self.preservesSuperviewLayoutMargins = true
self.layoutMargins = .zero
let imageView = UIImageView(image: UIImage(named: "jesus"))
imageView.contentMode = .center
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.clipsToBounds = true
self.clipsToBounds = true
imageView.backgroundColor = UIColor.red
self.addSubview(imageView)
imageView.leftAnchor.constraint(equalTo: self.layoutMarginsGuide.leftAnchor).isActive = true
imageView.rightAnchor.constraint(equalTo: self.layoutMarginsGuide.rightAnchor).isActive = true
imageView.topAnchor.constraint(equalTo: self.layoutMarginsGuide.topAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: self.layoutMarginsGuide.bottomAnchor).isActive = true
}
}
I believe that you forgot something those are required.
intrinsicContentSize
on ImageView and LabeltranslatesAutoresizingMaskIntoConstraints
property to falseconstraint for bottom
of the outmost frame
viewCall layoutIfNeeded()
on frame
view
top.widthAnchor.constraint(equalTo: bottom.widthAnchor).isActive = true top.heightAnchor.constraint(equalTo: bottom.heightAnchor).isActive = true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With