UICollectionViewFlowLayout empty space with variable cell width and height

I am trying to define a custom thread layout for a UICollectionView by subclassing UICollectionViewFlowLayout. The layout I want looks like this:

layout

As you can see, I divided the collection view into 2 equal lines along the horizontal middle gap. The top row is split into a third to give 3 columns, and the bottom rows are halved to give 2 columns.

Everything seems to work and looks great until you scroll to the right (scroll through the collection view - UICollectionViewScrollDirectionHorizontal), and you will see a large space there after 5 cells have finished displaying:

layout

I have no idea why this happens, however it seems that the empty space looks about the same as the cell from the top row; one third of the width of the collection view.

This is how I set up a subclass of UICollectionView and UICollectionViewFlowLayout

- (void)loadView { [super loadView]; [self setupCollectionView]; } - (void)setupCollectionView { CustomFlowLayout *flowLayout = [[CustomFlowLayout alloc] init]; flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; flowLayout.minimumInteritemSpacing = 0.0; flowLayout.minimumLineSpacing = 0.0f; CGRect frame = CGRectMake(0, 0, 748, 1024); UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:flowLayout]; [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:CollectionViewCellID]; collectionView.delegate = self; collectionView.dataSource = self; collectionView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; collectionView.backgroundColor = [UIColor whiteColor]; collectionView.pagingEnabled = YES; self.collectionView = collectionView; [self.view addSubview:self.collectionView]; } #pragma mark - UICollectionViewDataSource - (NSInteger )numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return 1; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return 5; } 

The size of the elements in the collection view is determined by the layout configuration for this section, so I implement collectionView:layout:sizeForItemAtIndexPath: as follows:

 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return [collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath].size; } 

My custom subclass of UICollectionViewLayout is implemented as follows:

 @implementation CustomFlowLayout - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { NSArray* attributesToReturn = [super layoutAttributesForElementsInRect:rect]; for (UICollectionViewLayoutAttributes* attributes in attributesToReturn) { if (nil == attributes.representedElementKind) { NSIndexPath* indexPath = attributes.indexPath; attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame; } } return attributesToReturn; } - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewLayoutAttributes* currentItemAttributes = [super layoutAttributesForItemAtIndexPath:indexPath]; if (!currentItemAttributes) { currentItemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; } float height = self.collectionView.frame.size.height; float width = self.collectionView.frame.size.width; CGRect frame = CGRectZero; switch (indexPath.row) { case 0: frame.size = CGSizeMake(width/3, height/2); frame.origin = CGPointMake(0, 0); break; case 1: frame.size = CGSizeMake(width/3, height/2); frame.origin = CGPointMake(width/3, 0); break; case 2: frame.size = CGSizeMake(width/3, height/2); frame.origin = CGPointMake(2*width/3, 0); break; case 3: frame.size = CGSizeMake(width/2, height/2); frame.origin = CGPointMake(0, height/2); break; case 4: frame.size = CGSizeMake(width/2, height/2); frame.origin = CGPointMake(width/2, height/2); break; default: break; } currentItemAttributes.frame = frame; currentItemAttributes.size = frame.size; return currentItemAttributes; } 

Does anyone have any ideas why I have a large empty space after all cells have been displayed? Or someone has a better approach to rendering the layout I'm doing. All code is available as an example Xcode project here . Answers, tips, thoughts, requests for traction are welcome.

+6
source share
1 answer

The problem was that if there were two rows of cells having different widths, the contentSize of the collection was taken into account in such a way that it left an area with white space to the right. To fix the problem, it was necessary simply:

 - (CGSize)collectionViewContentSize { return CGSizeMake(1024, 748); } 

Updated Github repository with changes here . Hope this helps someone in the future.

+4
source

Source: https://habr.com/ru/post/946045/


All Articles