How to adjust height of UICollectionView to be the height of the content size of the UICollectionView?
I would suggest the following:
- Add a height constraint to your collection view.
- Set its priority to 999.
- Set its constant to any value that makes it reasonably visible on the storyboard.
- Change the bottom equal constraint of the collection view to greater or equal.
- Connect the height constraint to an outlet.
- Every time you reload the data on the collection view do the following:
You may also want to consider the Inset of the collection view by adding it to the content size.
Code Sample:
CGFloat height = myCollectionView.collectionViewLayout.collectionViewContentSize.height
heightConstraint.constant = height
self.view.setNeedsLayout() Or self.view.layoutIfNeeded()
Explanation: Extra, You don't have to read if you understand it. obviously!!
The UI will try to reflect all the constraints no matter what are their priorities. Since there is a height constraint with lower priority of (999), and a bottom constraint of type greater or equal. whenever, the height constraint constant is set to a value less than the parent view height the collection view will be equal to the given height, achieving both constraints.
But, when the height constraint constant set to a value more than the parent view height both constraints can't be achieved. Therefore, only the constraint with the higher priority will be achieved which is the greater or equal bottom constraint.
The following is just a guess from an experience. So, it achieves one constrant. But, it also tries to make the error in the resulted UI for the other un-achieved lower priority constraint as lowest as possible. Therefore, the collection view height will be equal to the parent view size.
Constrain UICollectionView height to match height of contents
A better location to update the constraint is viewDidLayoutSubviews
, which gets called after every re-layout (orientation changes, size changes, etc). Also, it's more reliable to ask the collection view layout for the content size:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Update placeholder constraint
self.heightConstraint.constant = self.collection.collectionViewLayout.collectionViewContentSize.height
}
UICollectionView autosize height
I solved this eventually by fixing all Auto Layout issues, fixing the height of the collection view using a constraint. Then, whenever I know the content has changed I update the value of the constraint using the value collectionView.contentSize.height
:
self.verticalLayoutConstraint.constant = self.collectionView.contentSize.height;
Then the collection view is resized properly and it behaves nicely within the overall scrollview. I have updated the GitHub test project with my changes.
To me, doing this by updating the constraint manually instead of being able to tell iOS: "make the frame height of the collection view as large as needed" does not feel right to me, but it's the best I have come up with so far. Please post a better answer if you have one.
How to dynamically change the height of UICollectionView to adapt to content size
At what point are you trying to read the collectionViewContentSize
value?
If you are doing that right after a reloadData()
call - that might not give you accurate results because these calls are deferred to be executed at some point on main thread. The content size won't change immediately after doing the reloadData()
call.
Try following :
- Declare a variable inside the class like this.
private var contentSizeObservation: NSKeyValueObservation?
- Start observing contentSize changes.
contentSizeObservation = deadlinesCollectionView.observe(\.contentSize, options: .new, changeHandler: { [weak self] (cv, _) in
guard let self = self else { return }
self.deadlineCollectionViewHeight.constant = cv.collectionViewLayout.collectionViewContentSize.height
})
- Do NOT Forget to clean this up in
deinit
call -
deinit {
contentSizeObservation?.invalidate()
}
This approach will make sure that your collectionView is always as big in height as it's content.
How to determine height of UICollectionView with FlowLayout
Whoa! For some reason, after hours of research, I now found a pretty easy answer to my question: I was completely searching in the wrong place, digging through all the documentation I could find on UICollectionView
.
The simple and easy solution lies in the underlying layout: Just call collectionViewContentSize
on your myCollectionView.collectionViewLayout
property and you get the height and width of the content as CGSize
. It's as easy as that.
Size height for item collection view
create Constraint CollectionViewHeight.
@IBOutlet weak var collectionViewHeight: NSLayoutConstraint!
and then, try this Code.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let height = collectionView.collectionViewLayout.collectionViewContentSize.height
collectionViewHeight.constant = height
self.view.layoutIfNeeded()
}
How to set UICollectionViewCell Width and Height programmatically
Use this method to set custom cell height width.
Make sure to add this protocols
UICollectionViewDelegate
UICollectionViewDataSource
UICollectionViewDelegateFlowLayout
If you are using swift 5 or xcode 11 and later you need to set Estimate Size
to none
using storyboard in order to make it work properly. If you will not set that than below code will not work as expected.
Swift 4 or Later
extension YourViewController: UICollectionViewDelegate {
//Write Delegate Code Here
}
extension YourViewController: UICollectionViewDataSource {
//Write DataSource Code Here
}
extension YourViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: screenWidth, height: screenWidth)
}
}
Objective-C
@interface YourViewController : UIViewController
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(CGRectGetWidth(collectionView.frame), (CGRectGetHeight(collectionView.frame)));
}
Related Topics
Ineligible Devices Section Appeared in Xcode 6.X.X
How to Use Uivisualeffectview to Blur Image
Issue Detecting Button Cellforrowat
How to Determine the Os Version At Runtime in Os X or iOS (Without Using Gestalt)
How to Launch Safari and Open Url from iOS App
iOS 9: How to Change Volume Programmatically Without Showing System Sound Bar Popup
How to Implement Re-Ordering of Coredata Records
Displaying Splash Screen for Longer Than Default Seconds
Passing Data Between View Controllers Using Segue
Dismiss Keyboard by Touching Background of Uitableview
How to Validate an E-Mail Address in Swift
Add Placeholder Text Inside Uitextview in Swift
Mkmapview: Instead of Annotation Pin, a Custom View
Displaying a Stock iOS Notification Banner When Your App Is Open and in the Foreground
Importing Project-Swift.H into a Objective-C Class...File Not Found