1

I would like the UITableView's row height to respond to changes in the user's preferred text size. For example, when the preferred text size increases, I would like to increase the row height by a proportional amount. Here's what I have so far:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self.tableView reloadData];

    // observe when user changes preferred text size
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(preferredContentSizeChanged:) name:UIContentSizeCategoryDidChangeNotification object:nil];
}

- (void)preferredContentSizeChanged:(NSNotification *)notification
{ 
    [self.tableView reloadData];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];

    // leverage Text Kit's Dynamic Type
    cell.textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];

    cell.textLabel.text = @"All work and no play...";

    return cell;
}

So what's the best way to calculate a row height that reflects the user's preferred text size?

bilobatum
  • 8,918
  • 6
  • 36
  • 50
  • possible duplicate of [How to resize superview to fit all subviews with autolayout?](http://stackoverflow.com/questions/18118021/how-to-resize-superview-to-fit-all-subviews-with-autolayout) – JosephH Jan 13 '14 at 13:18

2 Answers2

2

I have recently accomplished this and found it to be very simple. Instead of using sizeWithFont: you should use the new boundingRectWithSize:options:attributes:context method in iOS 7.

Set up your table view cell as usual and specify the preferredFontForTextStyle: on your text label as such:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableViewCellIdentifier forIndexPath:indexPath];

    //set your table view cell content here
    [[cell textLabel] setText:@"Lorem ipsum dolour sit amet."];
    [[cell textLabel] setNumberOfLines:0];
    [[cell textLabel] setLineBreakMode:NSLineBreakByWordWrapping];
    [[cell textLabel] setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody]];

    return cell;
}

Then to correctly determine the size of the text label, evaluate the boundingRectWithSize:options:attributes:context to calculate the required height.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //add your table view cell content here
    NSString *string = @"Lorem ipsum dolor sit amet.";

    NSDictionary *attributes = @{NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleBody]};

    CGRect frame = [string boundingRectWithSize:CGSizeMake(CGRectGetWidth(tableView.bounds), CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) attributes:attributes context:nil];

    return ceilf(CGRectGetHeight(frame);
}

You may want to subclass your table view cell also to listen for UIContentSizeCategoryDidChangeNotification notifications at which point you can update your UI when the user changes their preferences in Settings.app

- (void)contentSizeCategoryDidChangeNotificationHandler:(NSNotification *)notification
{
    [[self textLabel] setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody]];
}

Should you require additional padding around the text label, you can define a constant value such as

static CGFloat const TableViewCellPadding = 10.0;

With this in place, you can either add a constant value to the value returned from tableView:heightForRowAtIndexPath:

return (ceilf(CGRectGetHeight(frame) + TableViewCellPadding);

Or you could inset the frame returned from boundingRectWithSize:options:attributes:context as such:

CGRect frame = [string boundingRectWithSize:CGSizeMake(CGRectGetWidth(tableView.bounds), CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) attributes:attributes context:nil];

frame = CGRectInset(frame, 0.0, TableViewCellPadding);
Zack Brown
  • 5,990
  • 2
  • 41
  • 54
  • So you're setting the row height to the exact height of the text without adding any padding above and below the text? The rows are going to be very short and visually unappealing. I think you have provided only half a solution here. How would you calculate the padding? – bilobatum Nov 21 '13 at 21:39
  • Padding would be added at the users behest. I actually do this myself by defining a static constant which is applied using `CGRectInset` or more preferably added to the height returned from `CGRectGetHeight`. – Zack Brown Nov 21 '13 at 22:27
  • In your code, row height is returned by a table view delegate method, so when exactly are you going to add a constant value to the row height? And how would you use CGRectInset to configure the height of a table cell? Post the code. – bilobatum Nov 22 '13 at 00:22
  • I omitted the code for adding padding as this wasn't part of the OPs question. Using `CGRectInset` or adding a constant value to the value returned from `tableView:heightForRowAtIndexPath:` is a simple process. Regardless, I have amended my answer to reflect this. – Zack Brown Nov 22 '13 at 09:34
-3

use this method:

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
 {
      NSString *fieldLabel = labelCell.textLabel.text;

     CGSize textSize = [fieldLabel sizeWithFont:[UIFont fontWithName:@"Georgia" size:17.0f] constrainedToSize:CGSizeMake([UIScreen mainScreen].bounds.size.width-20, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
     float newHeight = textSize.height+22.0f;
     return newHeight;
 }

Add below code to cellForRowAtIndexPath

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
      static NSString *cellID = @"Cell";
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];

      UILabel *lblfield=[[UILabel alloc] init];
      NSString *fieldLabel=[NSString stringWithFormat:@"%@",labelCell.textLabel.text];
      CGSize textSize = [fieldLabel sizeWithFont:[UIFont fontWithName:@"Georgia" size:17.0f]      constrainedToSize:CGSizeMake([UIScreen mainScreen].bounds.size.width-20, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
      float newHeight = textSize.height+22.0f;
      lblfield.frame=CGRectMake(10, 0, [UIScreen mainScreen].bounds.size.width, newHeight);
      lblfield.backgroundColor=[UIColor clearColor];
      lblfield.text=strusername;
      [cell addSubview:lblfield];
      return cell;
 }
Pradhyuman sinh
  • 3,936
  • 1
  • 23
  • 38