I have a UICollectionView, a button that creates a new cell in collection view. And I want UICollectionView to adjust it's size according to it's content size (when there are one or two cells then UICollectionView is short, if there are a lot of cell UICollectionView is big enough).
I know how to get content size:
collectionView.collectionViewLayout.collectionViewContentSize
But I have no idea where to use this value. I would appreciate if somebody help me to figure out how to make UICollectionView auto adjust it's height.
UPD:
I published on GitHub a demo project that describes the problem: https://github.com/avokin/PostViewer
I don't think content size is what you're after. I think you're wanting to adjust the amount of screen real estate consumed by the collection view, right? That's going to require adjustment of the frame. The content size includes the off-screen (scrolling) area as well as the on screen view.
I don't know of anything that would prevent you from just changing the frame size on the fly:
collectionView.frame = CGRectMake (x,y,w,h);
[collectionView reloadData];
If I'm understanding you correctly.
Use a height constraint for the collection view and update its value with the content height when needed. See this answer: https://stackoverflow.com/a/20829728/3414722
Steps to change the UICollectionView frame:
Set the "translatesAutoresizingMaskIntoConstraints" property to YES for the collectioview's superview (If you are using AUTOLAYOUT)
Then update the collectioview's frame as :
collectionView.frame = CGRectMake (x,y,w,h);
[collectionView reloadData];
You need to constrain the collection view height to the height of your content:
I'm using SnapKit in the following code.
First constrain the collection view edges to its superview:
private func constrainViews() {
collectionView?.translatesAutoresizingMaskIntoConstraints = true
collectionView?.snp.makeConstraints { make in
make.edges.equalToSuperview()
heightConstraint = make.height.equalTo(0).constraint
}
}
Next calculate the height and set the height to the height constraint offset. I'm letting the flow layout do the work, and then calculating the height based on the bottom edge of the last layout attribute:
override func viewDidLayoutSubviews() {
guard
let collectionView = collectionView,
let layout = collectionViewLayout as? UICollectionViewFlowLayout
else {
return
}
let sectionInset = layout.sectionInset
let contentInset = collectionView.contentInset
let indexPath = IndexPath(item: tags.count, section: 0)
guard let attr = collectionViewLayout.layoutAttributesForItem(at: indexPath) else {
return
}
// Note sectionInset.top is already included in the frame's origin
let totalHeight = attr.frame.origin.y + attr.frame.size.height
+ contentInset.top + contentInset.bottom
+ sectionInset.bottom
heightConstraint?.update(offset: totalHeight)
}
Note that in the example, I always have one special tag not included in my items tags
count, so the line:
let indexPath = IndexPath(item: tags.count, section: 0)
would need to be something like if items.count > 0 ... let indexPath = IndexPath(item: tags.count - 1, section: 0)
in most other code.