I am using SnapKit for auto layout in my iOS app.
I need to show an image view at the very top of the screen. It will have an image of dynamic height and width. I need its top edge to be aligned with top of the view. I need it to be horizontally centred. I need it to have a left and right margin from the screen of greater than or equal to 10. I need its height to be dynamic based on the content with maximum height equal to 300. I need it to maintain its aspect ratio and reduce its width or height as needed automatically using auto layout.
I thought the below code should do the work:
let padding = 10.0
let preview = UIImageView()
preview.setContentHuggingPriority(.required, for: .vertical)
preview.setContentHuggingPriority(.required, for: .horizontal)
preview.backgroundColor = .red
preview.contentMode = .scaleAspectFit
let image = UIImage(named: "demo3")!
preview.image = image
preview.clipsToBounds = true
view.addSubview(preview)
preview.snp.makeConstraints { make in
make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
make.centerX.equalToSuperview()
make.left.right.greaterThanOrEqualToSuperview().inset(padding).priority(.required)
make.height.lessThanOrEqualTo(300).priority(.required)
make.width.equalTo(preview.snp.height).multipliedBy(image.size.width / image.size.height).priority(.required)
}
This seems to work fine for landscape images (width longer than height) but it breaks in portrait images:
Works in landscape images:
Fails in portrait images. Notice how the height is no longer lessThanOrEqualTo(300)
:
This is due to Xcode prints a warning that it was unable to satisfy the constraints and it had to break the height constraint:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<SnapKit.LayoutConstraint:[email protected]#54 UIImageView:0x7f81b19101e0.centerX == UIView:0x7f81b183dc30.centerX>",
"<SnapKit.LayoutConstraint:[email protected]#55 UIImageView:0x7f81b19101e0.right >= UIView:0x7f81b183dc30.right - 12.0>",
"<SnapKit.LayoutConstraint:[email protected]#56 UIImageView:0x7f81b19101e0.height <= 300.0>",
"<SnapKit.LayoutConstraint:[email protected]#57 UIImageView:0x7f81b19101e0.width == UIImageView:0x7f81b19101e0.height * 0.666748046875>",
"<NSLayoutConstraint:0x600003e37a20 'UIView-Encapsulated-Layout-Width' UIView:0x7f81b183dc30.width == 430 (active)>"
)
Will attempt to recover by breaking constraint
<SnapKit.LayoutConstraint:[email protected]#56 UIImageView:0x7f81b19101e0.height <= 300.0>
I would have expected it to reduce its width while maintaining the aspect ratio to satisfy the conditions. But it doesn't do so.
I am using SnapKit for auto layout in my iOS app.
I need to show an image view at the very top of the screen. It will have an image of dynamic height and width. I need its top edge to be aligned with top of the view. I need it to be horizontally centred. I need it to have a left and right margin from the screen of greater than or equal to 10. I need its height to be dynamic based on the content with maximum height equal to 300. I need it to maintain its aspect ratio and reduce its width or height as needed automatically using auto layout.
I thought the below code should do the work:
let padding = 10.0
let preview = UIImageView()
preview.setContentHuggingPriority(.required, for: .vertical)
preview.setContentHuggingPriority(.required, for: .horizontal)
preview.backgroundColor = .red
preview.contentMode = .scaleAspectFit
let image = UIImage(named: "demo3")!
preview.image = image
preview.clipsToBounds = true
view.addSubview(preview)
preview.snp.makeConstraints { make in
make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
make.centerX.equalToSuperview()
make.left.right.greaterThanOrEqualToSuperview().inset(padding).priority(.required)
make.height.lessThanOrEqualTo(300).priority(.required)
make.width.equalTo(preview.snp.height).multipliedBy(image.size.width / image.size.height).priority(.required)
}
This seems to work fine for landscape images (width longer than height) but it breaks in portrait images:
Works in landscape images:
Fails in portrait images. Notice how the height is no longer lessThanOrEqualTo(300)
:
This is due to Xcode prints a warning that it was unable to satisfy the constraints and it had to break the height constraint:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<SnapKit.LayoutConstraint:[email protected]#54 UIImageView:0x7f81b19101e0.centerX == UIView:0x7f81b183dc30.centerX>",
"<SnapKit.LayoutConstraint:[email protected]#55 UIImageView:0x7f81b19101e0.right >= UIView:0x7f81b183dc30.right - 12.0>",
"<SnapKit.LayoutConstraint:[email protected]#56 UIImageView:0x7f81b19101e0.height <= 300.0>",
"<SnapKit.LayoutConstraint:[email protected]#57 UIImageView:0x7f81b19101e0.width == UIImageView:0x7f81b19101e0.height * 0.666748046875>",
"<NSLayoutConstraint:0x600003e37a20 'UIView-Encapsulated-Layout-Width' UIView:0x7f81b183dc30.width == 430 (active)>"
)
Will attempt to recover by breaking constraint
<SnapKit.LayoutConstraint:[email protected]#56 UIImageView:0x7f81b19101e0.height <= 300.0>
I would have expected it to reduce its width while maintaining the aspect ratio to satisfy the conditions. But it doesn't do so.
Share Improve this question edited yesterday sudoExclamationExclamation asked yesterday sudoExclamationExclamationsudoExclamationExclamation 8,73610 gold badges51 silver badges117 bronze badges1 Answer
Reset to default 2I think what you need here is replacing
make.left.right.greaterThanOrEqualToSuperview().inset(padding).priority(.required)
with
make.left.greaterThanOrEqualToSuperview().inset(padding)
make.right.lessThanOrEqualToSuperview().inset(padding)
For me it works perfectly fine now!