Resize UILabel for text inside custom UITableViewCell regardless of width

I am trying to get a shortcut in a cell for the correct size, regardless of device or orientation. I can set the line height correctly. I can also set the height of the labels in cellForRowAtIndexPath and check this in my logs. But by the time it reaches willDisplayRowAtIndexPath , the height of the label has changed, but only when the cell does not have a width of 320 pixels.

Here is my code -

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"CustomCellIdentifier"; CustomInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil){ cell = [[CustomInfoCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier]; NSArray *objects = [[NSBundle mainBundle] loadNibNamed:@"CustomInfoCell" owner:self options:nil]; cell = objects[0]; } // Configure the cell... cell.customTitleLabel.text = [_data[indexPath.row] objectForKey:t]; CGFloat labelWidth = self.view.frame.size.width-40; NSLog(@"labelWidth:%f",labelWidth); NSString *text = [_data[indexPath.row] objectForKey:d];//correct text CGSize labelsize=[text sizeWithFont:cell.customDetailLabel.font constrainedToSize:CGSizeMake(labelWidth, 2000.0) lineBreakMode:cell.customDetailLabel.lineBreakMode]; NSLog(@"labelsize:%f,%f",labelsize.width,labelsize.height); //For testing cell.customDetailLabel.backgroundColor = [UIColor redColor]; NSLog(@"Pre: %@",cell.customDetailLabel); cell.customDetailLabel.frame=CGRectMake(20, 22, labelWidth, labelsize.height); cell.customDetailLabel.text = text; NSLog(@"Post: %@",cell.customDetailLabel); return cell; } 

In willDisplayRowAtIndexPath I also print label information. One line prints here -

 2013-03-24 18:33:44.009 Bridge Alert[57793:1e503] labelWidth:728.000000 2013-03-24 18:33:44.010 Bridge Alert[57793:1e503] labelsize:713.000000,76.000000 2013-03-24 18:33:44.010 Bridge Alert[57793:1e503] Pre: <UILabel: 0xad3eaf0; frame = (20 20; 280 21); text = 'Detail'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>> 2013-03-24 18:33:44.011 Bridge Alert[57793:1e503] Post: <UILabel: 0xad3eaf0; frame = (20 22; 728 76); text = 'Detail'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>> 2013-03-24 18:33:44.011 Bridge Alert[57793:1e503] Text set: <UILabel: 0xad3eaf0; frame = (20 22; 728 76); text = 'A bridge is considered "f...'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>> 2013-03-24 18:33:44.014 Bridge Alert[57793:1e503] Display:<UILabel: 0xad3eaf0; frame = (20 20; 728 190); text = 'A bridge is considered "f...'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x17372eb0>> 

As you can see, the size of the label is changed using the display. I assume that the height is recalculated somehow, based on whether the cell was 320 pt wide, which is the inline width of the UITableViewCell.

How can I assign a label correctly?

+4
source share
6 answers

Have you tried disabling autoscaling? This will eliminate unnecessary (mostly useless) restrictions.

+3
source

This is what worked for me with minimal code using AutoLayout .

In my ViewController, I added the following methods

 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { NSString * yourText = //place here the text you want to calculate its size; return 40 + [self heightForText:yourText]; } -(CGFloat)heightForText:(NSString *)text { NSInteger MAX_HEIGHT = 2000; UITextView * textView = [[UITextView alloc] initWithFrame: CGRectMake(0, 0, 320, MAX_HEIGHT)]; textView.text = text; textView.font = [UIFont boldSystemFontOfSize:12]; [textView sizeToFit]; return textView.frame.size.height; } 

This code basically resizes the UITableViewCell based on the size of my UILabel + padding number, which in my case I defined as 40.

After that, I had to add a couple of constraints, as shown below, to make UILabel β€œstretch”, as UITableViewCell does

enter image description here

After launch:

enter image description here

Note. I used different code snippets from many threads in SO to come up with this solution. I'm sorry that I could not remember everything that they mentioned here.

Hope this works for you guys.

Greetings

+19
source

In my opinion, a builder / storyboard interface can be useful, but often adds another unnecessary level of complexity. I would just subclass UITableViewCell (like you, but I did it purely programmatically) and set the customDetailLabel frame using layoutSubviews.

+2
source

I had exactly the same problem, for some reason the height of the cue changes when it really displays. I ended up using the free Sensible TableView environment, which really allows you to resize correctly (even resizes the cell if you decide to use multi-line UILabel). The structure also automatically assigned label text from my object property, which was really cool.

+1
source

Try overriding setFrame in your CustomInfoCell class to enable resizing of elements in a cell after setting the frame. I have included the code that I use to execute this, which is slightly different from your implementation. Also, on your label, I set the UIViewAutoresizingFlexibleWidth mask to UIViewAutoresizingFlexibleWidth .

Type this at the top of the file:

 static void *kKVOContext; // See: http://www.dribin.org/dave/blog/archives/2008/09/24/proper_kvo_usage/ 

ViewDidLoad includes:

 [self.textLabel addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:&kKVOContext]; [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]]; 

Then turn on:

 - (void)setFrame:(CGRect)frame { [super setFrame:frame]; //Resize elements to fit inside new frame [self textChanged]; } - (CGSize)textLabelSize { BOOL portrait = UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation); CGFloat width = portrait ? [UIScreen mainScreen].bounds.size.width : [UIScreen mainScreen].bounds.size.height; CGFloat maxWidth = width - 90 - TEXT_X_LEFT_PADDING; CGSize maximumLabelSize = CGSizeMake(maxWidth, 10000); return [self.textLabel.text sizeWithFont:self.textLabel.font constrainedToSize:maximumLabelSize lineBreakMode:self.textLabel.lineBreakMode]; } - (CGFloat)cellHeight { CGSize expectedLabelSize = [self textLabelSize]; return (self.titleLabel.frame.origin.y+self.titleLabel.frame.size.height) + expectedLabelSize.height; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqual:@"text"] && object == self.textLabel) { [self textChanged]; } if(context != &kKVOContext) { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } - (void)orientationChanged:(NSNotification *)note { //Resize text on orientation change [self textChanged]; } - (void)textChanged { CGRect newFrame = self.textLabel.frame; newFrame.size = [self textLabelSize]; if(!CGRectEqualToRect(self.textLabel.frame, newFrame)) { self.textLabel.frame = newFrame; } } 
0
source

Just submit my own simplified approach, based on @Paulo, but now with width adaptable and more accurate storyboard restrictions.

(Swift)

 override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { let cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier")! // Use subclass of UITableViewCell if your cell is complex. let label = cell.viewWithTag(3001) as! UILabel; label.text = someStringArray[indexPath.row] label.sizeToFit(); let y = label.frame.origin.y let height = label.frame.size.height let paddingBottom: CGFloat = 8 // add other controls/view height if any after the expand label return y + height + paddingBottom } 
0
source

All Articles