I'm trying to create custom cells with UIStackView and UICollectionViewListCell.
- The layout is simple. The stack view's edges are pinned to content view's layout margins guide.
- The stack view's axis is
.horizontal
- The stack view's alignment is
.center
- The stack view has only one arranged subview (a text label).
There are two ways to implement such cells:
Traditional Cell
Subclass UICollectionViewCell
or UICollectionViewListCell
and layout views in it's contentView
property directly.
However, stackView.alignment = .center
case the stack view renders in wrong size. It's height a bit larger that it's content.
If I add a second view to the stack view, for example an empty UIView, the layout works again.
New Content Configuration API
Use UIContentView
and UIContentConfiguration
to create a custom content view.
However, with stackView.alignment = .center
, the app crashes.
Thread 1: "Content view returned an invalid size {353, 1.7976931348623157e+308} from -systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: which is not allowed. If you have implemented a custom content view, you need to add constraints inside it so that its size is not ambiguous, or you need to manually compute and return a valid size. Content view: <Test.TextLabelContentView: 0x143f0e8a0; frame = (0 0; 353 44); gestureRecognizers = <NSArray: 0x600000f9edc0>; layer = <CALayer: 0x6000001d3d40>>"
If I add a second view to the stack view, for example an empty UIView, the layout works again and the app does not crash.
Reproduce
You can reproduce this problem with the attachment HomeViewController.swift
How does UIStackView determine it's size
We create a horizontal stack view whose alignment is center
. When it has only one arranged subview, the stack view can't determine it's own height.
If such a stackview is in a UIContentView
, the app will crash. If it's in a tranditional subclass cell, the stackview's height is incorrect (a bit larger than it's content).
If such a stackview has more than one arranged subvies, everything works great.
Is this expected?
let stackView = UIStackView()
stackView.axis = .horizontal
stackView.alignment = .center
The behavior of cell's systemLayoutSizeFitting
The app crashes because systemLayoutSizeFitting(_:withHorizontalFittingPriority:verticalFittingPriority:)
returns an invalid value.
Then I override this method in the cell and find that the targetSize
parameter passed to this method is (353.0, 1.7976931348623157e+308). The height is 1.7976931348623157e+308, but why? It looks strange to me.
I thought the value should be UIView.layoutFittingCompressedSize.height
.
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
// `targetSize` is (353.0, 1.7976931348623157e+308)
return super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
}