UICollectionViewCell using prototype sizes

I have a UICollectionView with three different prototype cells, each of which has a different height set through the Storyboard. At run time, Collection View uses its own cell size, ignoring my storyboards.

I am currently using collectionView: layout: sizeForItemAtIndexPath: with several conditional settings to set each CGSize directly.

Is there a better way to set cell sizes? I can't seem to get the size of the storyboard that each cell has, and CGSizeMake seems too tight and not very flexible.

+6
source share
3 answers

It seems that there is currently no easy way:

  • Extract prototype prototypes of UICollectionViewCell from the storyboard (s).
  • Manage prototype sizes in only one place (instead of entering them in the prototype of the Storyboard cell and implementing sizeForItemAtIndexPath ).

The proposed method here (for UITableViews) does not work, since using dequeueReusableCellWithReuseIdentifier in sizeForItemAtIndexPath will lead to an undefined loop.

However, I managed to do it as follows :

  • Add a unique (across all UICollectionViewCell in each storyboard) reuse identifier to each of your prototype UICollectionView in all storyboards.

  • Add a Run script build phase to the project using a script that pulls the frame sizes of the UICollectionViewCell from all the storyboards.

     output=${PROJECT_DIR}/StoryboardPrototypeCellSizes.h printf "@{" > $output for storyboard in $(find ${PROJECT_DIR} -name "*.storyboard") do echo "Scanning storyboard $storyboard..." delimiter= for line in $(xpath $storyboard "//collectionViewCell/@reuseIdentifier[string-length()>0] | //collectionViewCell/rect" 2>&-) do case $line in reuseIdentifier*) reuseIdentifier=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) ;; width*) if [ -n "$reuseIdentifier" ]; then width=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) fi ;; height*) if [ -n "$reuseIdentifier" ]; then height=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) fi ;; esac if [ -n "$reuseIdentifier" ] && [ -n "$width" ] && [ -n "$height" ]; then printf " $delimiter@ \"$reuseIdentifier\" : [NSValue valueWithCGSize:CGSizeMake($width, $height)]" >> $output unset reuseIdentifier unset width unset height delimiter=,\\n fi done done printf "};\n" >> $output 

    This creates a header file called StoryboardPrototypeCellSizes.h with the following example:

     @{@"TodayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 80)], @"SpecialDayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 42)], @"NameDayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 30)]}; 
  • Add a helper method to return the reuse identifier of the UICollectionViewCell in the view controller that controls your UICollectionView :

     - (NSString *)cellReuseIdentifierAtIndexPath:(NSIndexPath *)indexPath { switch (indexPath.item) { case 0: return @"TodayCell"; case 1: return @"SpecialDayCell"; case 2: return @"NameDayCell"; } return nil; } 
  • Be sure to use the same reuse identifier in cellForItemAtIndexPath :

     - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: [self cellReuseIdentifierAtIndexPath:indexPath] forIndexPath:indexPath]; ... 
  • Finally, execute sizeForItemAtIndexPath :

     - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { NSDictionary *storyboardPrototypeCellSizes = #import "StoryboardPrototypeCellSizes.h" return [(NSValue *)storyboardPrototypeCellSizes[ [self cellReuseIdentifierAtIndexPath:indexPath] ] CGSizeValue]; } 

This solution allows you to determine the cell sizes of the prototype UICollectionViewCell only once in the storyboard (s), and also does not perform compatibility with non-App-Store at run time.

**** Editing: **** You can also select UICollectionReusableView sizes by adding another script with the same contents and replacing "collectionViewCell" with "collectionReusableView" and renaming the header file, for example, in StoryboardReusableViewSizes.h

+2
source

There is no better way to set cell sizes. Cell sizes are used in several places in the UICollectionView - for positioning, for the scroll indicator. And it’s important to get them as quickly as possible if the user scrolls through the collection with thousands of small cells, for example. So create a cell and ask about its size, this is not an option. You must implement collectionView: layout: sizeForItemAtIndexPath: and it should work fast.

0
source

Do you use stream layout in UICollectionView ? If so, you can use the sizeForItemAtIndexPath method of the sizeForItemAtIndexPath protocol to specify the cell size. If you have no problem using the OSS components in your application, RFQuiltLayout can be used to achieve this.

-1
source

All Articles