UICollectionView dynamic cell width based on label width

I have a UICollectionView that loads cells from a reusable cell containing a shortcut. The array provides content for this label. I can change the width of the label depending on the width of the content using the sizeToFit parameter. But I can’t make the cell a suitable label.

Here is the code

- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. arrayOfStats = @[@"time:",@"2",@"items:",@"10",@"difficulty:",@"hard",@"category:",@"main"]; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection: (NSInteger)section{ return [arrayOfStats count]; } - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ return CGSizeMake(??????????); } - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ return 1; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ Cell *cell = (Cell *) [collectionView dequeueReusableCellWithReuseIdentifier:@"qw" forIndexPath:indexPath]; cell.myLabel.text = [NSString stringWithFormat:@"%@",[arrayOfStats objectAtIndex:indexPath.item]]; // make label width depend on text width [cell.myLabel sizeToFit]; //get the width and height of the label (CGSize contains two parameters: width and height) CGSize labelSize = cell.myLbale.frame.size; NSLog(@"\n width = %f height = %f", labelSize.width,labelSize.height); return cell; } 
+59
ios objective-c swift uicollectionview uicollectionviewcell
Apr 17 '14 at 13:49
source share
7 answers

In sizeForItemAtIndexPath return text size

 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ return [(NSString*)[arrayOfStats objectAtIndex:indexPath.row] sizeWithAttributes:NULL]; } 
+68
Apr 17 '14 at
source share

Checkout the code below, which you could give a very short CGSize.

 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ NSString *testString = @"SOME TEXT"; return [testString sizeWithAttributes:NULL]; } 
+24
Feb 25 '15 at 13:09
source share

In Swift 3

 let size = (arrayOfStats[indexPath.row] as NSString).size(attributes: nil) 
+17
Apr 21 '17 at 14:27
source share

Swift 4

 let size = (arrayOfStats[indexPath.row] as NSString).size(withAttributes: nil) 
+7
Aug 15 '18 at 8:37
source share

Swift 4.2 +

The principle is as follows:

  1. UICollectionViewDelegateFlowLayout (it contains the required method signature)

  2. Call the collectionView...sizeForItemAt .

  3. There is no need for an NSString String with an NSString to call size(withAttributes: method. Swift String has it out of the box).

  4. The attributes are the same as for the (NS)AttributedString , i.e. the font family, size, weight, etc. Optional parameter.




Example solution:

 extension ViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return "String".size(withAttributes: nil) } } 

But you most likely want to specify specific string attributes that match your cell, so the final return will look like this:

 // Replace "String" with proper string (typically array element). return "String".size(withAttributes: [ NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 14) ]) 
+7
Nov 13 '18 at 15:41
source share

I found a little trick for quick 4.2

For dynamic width and fixed height:

 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let label = UILabel(frame: CGRect.zero) label.text = textArray[indexPath.item] label.sizeToFit() return CGSize(width: label.frame.width, height: 32) } 

For dynamic height and fixed width:

 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let label = UILabel(frame: CGRect.zero) label.text = textArray[indexPath.item] label.sizeToFit() return CGSize(width: 120, height: label.frame.height) } 
+2
Jan 09 '19 at 13:53
source share

// add to the didload view

 UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; [layout setScrollDirection:UICollectionViewScrollDirectionHorizontal]; layout.estimatedItemSize = CGSizeMake(self.breadScrumbCollectionView.frame.size.width, 30); self.breadScrumbCollectionView.collectionViewLayout = layout; 
-one
Feb 06 '18 at 9:24
source share



All Articles