最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swift - iOS Autolayout - unable to have height be lessThanOrEqualTo - Stack Overflow

programmeradmin5浏览0评论

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 badges
Add a comment  | 

1 Answer 1

Reset to default 2

I 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!

发布评论

评论列表(0)

  1. 暂无评论