Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sizing UICollectionViewCell Based on label Size

I've got a UICollectionView that will have cells with labels of varying sizes. I'm trying to size the cell based on the size of the label. However sizeForItemAtIndexPath where I create the cell seems to be called before cellForItemAtIndexPath where I set the label.. Any ideas what I can do here?

- (void)getLabelSize:(UILabel *)label {
    float widthIs = [label.text boundingRectWithSize:label.frame.size options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ NSFontAttributeName:label.font } context:nil].size.width;

    width = widthIs;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    // Configure the cell
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
    UILabel *label = (UILabel *)[cell viewWithTag:1000];
    label.text = @"This is pretty long";
    [label sizeToFit];
    [self getLabelSize:label];
    NSLog([NSString stringWithFormat:@"%f", width]);
    cell.backgroundColor = [UIColor whiteColor];

    return cell;   
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(width, 50);
}
like image 728
Chris Byatt Avatar asked Feb 09 '15 12:02

Chris Byatt


3 Answers

In swift i have calculated the text size of label and updated the cell size according to it:

func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {


        let size: CGSize = keywordArray[indexPath.row].size(attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 14.0)])
        return CGSize(width: size.width + 45.0, height: keywordsCollectionView.bounds.size.height)
    }

as i have an extra button and padding i calculated that extra value which is 45.0

like image 96
Fay007 Avatar answered Oct 19 '22 09:10

Fay007


You need to store text for labels somewhere, in array for example, and separately define font for labels and define maxWidth, something like:

#define kLabelFont [UIFont fontWithName:@"SourceSansPro-Regular" size:12.0f]
#define maxWidth 100.0f

Then modify method getLabelSize, with string as an argument:

- (CGSize)getLabelSize:(NSString *)string {
     CGRect rect = [string boundingRectWithSize:(CGSize){maxWidth, CGFLOAT_MAX} options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ NSFontAttributeName: kLabelFont } context:nil];
     return rect.size;
}

Then you can get the size from both methods cellForItemAtIndexPath and sizeForItemAtIndexPath:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    ........
     NSString *string = [self.textArray objectAtIndex:indexPath.row];
     CGSize size = [self getLabelSize:string];
    ........
}
like image 36
Vladimir K Avatar answered Oct 19 '22 11:10

Vladimir K


Its solution for Swift 4.2 updated answer is to handle height and width of uicollectionview Cell on the basis of uilabel text

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
  let size = (self.FILTERTitles[indexPath.row] as NSString).size(withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14.0)])
    return CGSize(width: size.width + 38.0, height: size.height + 25.0)


}
like image 2
Shahzaib Maqbool Avatar answered Oct 19 '22 11:10

Shahzaib Maqbool