How can I update all the cell sizes of UICollectionView?
I am changing the frame of UICollectionView, and want to change its UICollectionViewCells sizes accordingly
I'm not sure what actually the problem is, but here is steps, that can help you to achieve what you want:
Define your collection view layout delegate (I assume that you use flow layout or its descendant)
Implement - collectionView:layout:sizeForItemAtIndexPath: (see docs) and compute cell size based on collectionView
When you change your collection view's frame call invalidateLayout (see docs). It will force delegate to call sizeForItemAtIndexPath
If you have any questions - feel free to ask. It would be better if you provide some code snippets and explain what kind of difficulties do you have.
Related
I have a UICollectionView. Its cells are prototyped in a Storyboard, and each cell has a hierarchy of views configured with Auto Layout.
I am implementing the following UICollectionViewDelegateFlowLayout protocol method:
collectionView(_ layout:sizeForItemAt)
Requirement: I need the final bounds of views within the cell, so that I can configure the contents of the cell. (The bounds are used in the creation of pixel-exact images with are then fed to the cells.) Please note that I can't calculate the bounds manually in sizeForItemAt, due to a complex hierarchy and Auto Layout: it would be too fragile.)
Problem: when collectionView(_ collectionView:, cellForItemAt) is called, final layout has not yet occurred. The various cell bounds are still the values set in the Storyboard.
Same thing for collectionView(_ collectionView:, willDisplay:, forItemAt:)
Same thing for viewDidLayoutSubviews
Question: how do I get accurate, final cell geometry information, before the cells are rendered? Cheers.
Thanks to AhmadF for the link to the answer. (See responses to question.)
Solution: tell the cell to layout before doing the calcs:
// ... De-queue cell here.
cell.setNeedsLayout()
cell.layoutIfNeeded()
// ... Perform geometry calcs here.
I have a UICollectionView with UICollectionViewFlowLayout. While testing with large data (5,000+ cells) I noticed a lag when loading. I found out that at loading the sizeForItemAtIndexPath is called for EVERY cell. Since I am doing a messaging like application and each cell is of different height, this causes height estimation to occur. I am not scrolling to the bottom or anything, just loading the view.
I have made a small app demonstrating what I am saying (look at the console to see that it is calling sizeForItemAtIndexPath for all cells) https://github.com/ftheo/CollectionViewLoadingBug
Any help would be appreciated. Thanks
Maybe there is no way to prevent calling sizeForItemAtIndexPath method...
That is normal design for calculating scroll content view size.
The collection view needs to know what size it's contents have, hence it calls -sizeForItemAtIndexPath:. There is no way around this.
Consider using a UITableView instead. It offers a method
-tableView:estimatedHeightForRowAtIndexPath: where you give it a rough guess for offscreen cells.
I have created my own layout by subclassing the UICollectionViewLayout class, and not the UICollectionViewFlowLayout one. Hence it seems that I cannot implement the method collectionView:layout:sizeForItemAtIndexPath:.
Unfortunately, I may want to change my cell's sizes dynamically. For instance, I have a set a little circular cells around a big cell. When the user exchange a small cell with the big one, I want the little cell to take the location and the size of the big cell, while the big cell would get as small as the little cell and it would take its location. I already managed to do the location exchange (with the moveItemAtIndexPath:toIndexPath: method) but the cell won't change their size.
I understand that the layout is the only responsible for updating item's size, but I can assure that I have tried anything and the cells still don't resize.
Does anyone have an idea of what I could do? I would be very grateful!
Custom UITableViewCell's subviews added in code using auto layout works (verified). However the whole point of doing this was to not have to calculate the height of each tableview cell and the delegate method heightForRowAtIndexPath expects a height while drawing the tableview.
How can I figure out this height based on content using the auto-layout (visual format language based addition in code already added and working) and return it to this heightForRowAtIndexPath?
Also I'm I can't really do this on a background thread (or can I?) and therefore if I have a UITableView using this backed by a list of say 1000 records, this will take forever, is that right?
Autolayout in this case just means that you don't need to calculate the frame sizes of your subviews within each cell. It's got nothing to do with the heightForRowAtIndexPath method - this is used by the table view to define the cell's frame, which will then inform the layout of the subviews.
Using Autolayout to determine the heights would likely be pretty slow, and you can't do it on a background thread. If you have 1000 rows then I'd consider a hierarchical structure instead of a single table as that will be pretty tedious to scroll through. You could also consider calculating the heights at the point of setting or creating the data.
You may be able to set up an offscreen view using your constraints, populate it with your data for each item, then record and cache the height. However you'd have to do this at the data end rather than in the height method, as it would be far too slow.
In iOS6, I cannot seem to get the width of the cell in cellForRowAtIndexPath for the grouped table style. Logging either the frame or the bounds for either the cell or its contentview returns 320 - even on iPad. I need to determine the cell width programmatically for any device as I need to calculate text sizes. Any advice in getting the correct cell width for a grouped tableview in cellForRowAtIndexpath would be appreciated please
The method you're using is the wrong place to calculate any kind of view-related constraints. The -tableView:cellForRowAtIndexPath: method is part of the table view's data source, not its delegate. You cannot rely on the frame or anything else here to be meaningful, it's meant as the place to configure the cell's /data/.
If you need to make calculations to view frames and such, and you're not using a custom subclass of UITableViewCell (i.e., you're just adding views to a default instance of UITableViewCell or configuring stock views), you would set up any frame-related / view specific attributes in the /delegate/ callback -tableView:willDisplayCell:forRowAtIndexPath: method. This is the place to configure any of the visible/view-related properties of your cell, and you will now have accurate layout information for the cell (its bounds will be correct, any layout/configuration of internal views will be complete, etc.).
If you have a custom subclass already, you can either do your view related property configuration in the delegate callback above, or you can do it in UIView's -layoutSubviews method, depending on your exact needs. For more information, see the documentation for -tableView:willDisplayCell:forRowAtIndexPath:.