systemLayoutSizeFitting ignoring layout constraints and using image view intrinsic size
Asked Answered
E

1

9

I'm using a custom layout for a UICollectionView. My cell should have fixed width and flexible height.

The cell is composed of a UImageView and a UIStackView. The UIImageView's constraints are the following:

image.top = cell.top
image.width = cell.width
image.height = image.width * 1.33
image.centerX = cell.centerX
image.bottom = stackView.top 

The stack view is similar, and is indeed tied to the bottom of the cell.

When the system is calling preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {

I'm performing some calculations to get the height of the cell.

let preferredAttributes = super.preferredLayoutAttributesFitting(layoutAttributes)


let size = CGSize(width: layoutAttributes.frame.width,
                  height: UILayoutFittingCompressedSize.height)

let preferredSize = systemLayoutSizeFitting(size,
                                            withHorizontalFittingPriority: .defaultHigh,
                                            verticalFittingPriority: .fittingSizeLevel)

It turns out that the preferredSize is being calculated using the imageView instrinsic size rather than respecting the constraints. So for a image with 850x850, (and a cell with 160 points of width) I'm getting a much higher height than what I expect and therefore a cell with a huge space to the bottom.

I managed to solve this problem with something that I feel like it's a hack.

I created a reference to the width constraint of the image, update it when I call this method with the fixed value that I get from layoutAttributes and call setNeedsLayout() and layoutIfNeeded() and this works. But I really don't like that I have to force the layout to be done again and update the width myself, not to mention that I loose performance.

How can this be done in a better way?

Thank you very much.

Effortless answered 28/6, 2017 at 11:45 Comment(1)
Can you try overriding viewDidLayoutSubviewsWattle
M
12

Are you have aspect ratio constraint? systemLayoutSizeFitting doesn't work properly when there is aspect ratio constraint.

First, try to set height constraint instead of aspect ratio on image and if it works, set the height constraint constant = image.width * 1.33 in code

Mishandle answered 28/6, 2017 at 12:42 Comment(3)
That's how I fixed it but I don't like that I have to do it myself and call layoutIfNeeded() cuz I'm also having performance issues and would like to avoid it.Capybara
Can you provide some more details about systemLayoutSizeFitting not working properly with aspect ratio? Do you have and references?Capybara
@NunoGonçalves Actually, it is a frequent problem. The systemLayoutSize use the intrinsicContentSize to calculate height, if you don't set the height constraint. Here is an another solution to this problem #25665216Mishandle

© 2022 - 2024 — McMap. All rights reserved.