Resizing a UICollectionViewCell after loading data using invalidateLayout

This question has been asked several times, but none of the answers are detailed enough for me to understand why and how everything works. For reference, other SO questions:

How to update cell size in UICollectionView after setting cell data?

Modify UICollectionView cells after their data is set

Where to determine the height of the dynamic size of a UICollectionViewCell?

I use MVC, but to keep things simple, let's say that I have a ViewController that in ViewWillAppear calls a web service to load some data. When the data has been downloaded, it calls

[self.collectionView reloadData] 

Self.collectionView contains 1 UICollectionViewCell (call it DetailsCollectionViewCell).

When self.collectionView is created, it first calls sizeForItemAtIndexPath, and then cellForItemAtIndexPath. This causes a problem for me, because only during cellForItemAtIndexPath do I set the web service result to DetailsCollectionViewCell via:

  cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"detailsCell" forIndexPath:indexPath]; ((DetailsCollectionViewCell*)cell).details = result; 

DetailsCollectionViewCell has a settings tool for property information that does some of the work that I need first to find out what the correct cell size should be.

Based on the related questions above, this seems like the only way to run sizeForItemAtIndexPath after cellForItemAtIndexPath calls

 [self.collectionView.collectionViewLayout invalidateLayout]; 

But this is when other questions do not work for me, because although it calls sizeForItemAtIndexPath and allows me to get enough information from the DetailsCollectionViewCell to set the correct height, it does not update the user interface until the user scrolls through the UICollectionView and my suppose that it has something to do with this line from the documentation

The current layout update occurs during the next view layout update cycle.

However, I do not understand how to get around this. It almost seems to me that I need to create a static method in DetailsCollectionViewCell so that I can pass the result of the web service the first time I pass sizeForItemAtIndexPath, and then just cache this result. But I hope there is a simple solution for automatically updating the user interface.

Thanks,

ps - The first question, so I hope that I follow all the rules correctly.

+7
uicollectionview uicollectionviewcell uicollectionviewlayout
source share
2 answers

In fact, from what I found, calling invalidateLayout will call sizeForItemAtIndexPath for all cells when the next cell is deleted (this is for iOS <8.0, since it will recalculate the layout from 8.0 in the next update of the view layout).

So, the solution I came across subclasses UICollectionView and overrides layoutSubviews something like this:

 - (void)layoutSubviews { if ( self.shouldInvalidateCollectionViewLayout ) { [self.collectionViewLayout invalidateLayout]; self.shouldInvalidateCollectionViewLayout = NO; } else { [super layoutSubviews]; } } 

and then call setNeedsLayout on cellForItemAtIndexPath and set the shouldInvalidateCollectionViewLayout parameter to YES. This worked for me on iOS> = 7.0. Thus, I also implemented the estimated sizes of the elements. thanks.

+2
source share

Here is my case and solution.

My CollectionView is in scrollView and I want my CollectionView and its cells to change as I scroll through my scrollView.

So, in my delegate UIScrollView: scrollViewDidScroll:

 [super scrollViewDidScroll:scrollView]; if(scrollView.contentOffset.y>0){ CGRect lc_frame = picturesCollectionView.frame; lc_frame.origin.y=scrollView.contentOffset.y/2; picturesCollectionView.frame = lc_frame; } else{ CGRect lc_frame = picturesCollectionView.frame; lc_frame.origin.y=scrollView.contentOffset.y; lc_frame.size.height=(3*(contentScrollView.frame.size.width/4))-scrollView.contentOffset.y; picturesCollectionView.frame = lc_frame; picturesCollectionViewFlowLayout.itemSize = CGSizeMake(picturesCollectionView.frame.size.width, picturesCollectionView.frame.size.height); [picturesCollectionViewFlowLayout invalidateLayout]; } 

I had to re-set the cell size of collectionViewFlowLayout and then invalidate its layout. Hope this helps!

0
source share

All Articles