I have UICollection view working with self sizing cells as shown on WWDC 2014.
I want to put it inside a UITableViewCell and display a cloud of tags (good reference of what I want to achieve is in Foursquare application: )
My problem is that with self sizing cells, content size is returned not properly. I prepared some quick demo to show the problem:
- (void)viewDidLoad
{
[super viewDidLoad];
self.elements = [NSMutableArray array];
for (int i = 0; i < 23; i++)
{
[self.elements addObject:[self randomString]];
}
UICollectionViewFlowLayout* layout = [[UICollectionViewFlowLayout alloc] init];
layout.estimatedItemSize = CGSizeMake(50, 30);
self.collectionView=[[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
UINib *cellNib = [UINib nibWithNibName:@"CustomCell" bundle:nil];
[self.collectionView registerNib:cellNib forCellWithReuseIdentifier:@"CustomCell"];
[self.collectionView setBackgroundColor:[UIColor blueColor]];
[self.view addSubview:self.collectionView];
}
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.collectionView.frame = CGRectMake(0, 0, self.collectionView.frame.size.width, self.collectionView.contentSize.height);
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [self.elements count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell* cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"CustomCell" forIndexPath:indexPath];
cell.customLabel.text = [self.elements objectAtIndex:[indexPath row]];
return cell;
}
When I do it old way and remove estimatedItemSize and use itemSize instead or delegate method to calculate a size - it works properly, so I think it is using estimatedItem size to get content size.
Is there any way to make it work with self sizing cells and autoresize UICollectionView to it's content ?
I ended up calculating the size on my own:
- (CGSize) sizeForCellAtIndexPath:(NSIndexPath*) indexPath isMoreButton:(BOOL) isMoreButton
{
TagCell* cell = (TagCell*) [[LayoutHelper sharedLayoutHelper] collectionCellFromNib:@"TagCell"];
cell.tagLabel.text = [self.contactHashTags objectAtIndex:indexPath.row];
CGSize size = [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
CGSizeMake(size.width, cell.frame.size.height);
}
- (CGSize) sizeForCellAtIndexPath:(NSIndexPath*) indexPath isMoreButton:(BOOL) isMoreButton
{
CGSize size = [self.dataSource sizeForCellAtIndexPath:indexPath isMoreButton:isMoreButton];
//limit cell to view width
size.width = MIN(size.width, self.frame.size.width);
return size;
}
My workaround... add an inset on the fly.
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
let isLastItem = indexPath.item == (collectionView.numberOfItems(inSection: indexPath.section) - 1)
guard isLastItem else {
return
}
DispatchQueue.main.async {
let inset = (cell.frame.maxX - collectionView.contentSize.width) + 10 // 10 is the right padding I want for my horizontal scroll
collectionView.contentInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: inset)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With