Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic height for static table cells with wrapping labels?

My text is two lines long in portrait mode. When I switch to landscape mode, it fits into a single line. I'm using static tableview cells via a storyboard; how can I resize the row to fit snugly?

The screen is a signin screen.

  • The first cell contains some explanation text
  • The second is a text field for entering the account name
  • The third is a secure text field for entering the password
  • The fourth (and last) cell contains the signin button. The return key on the keyboard submits the form or switches the focus as appropriate
like image 272
Steven Fisher Avatar asked Aug 16 '12 05:08

Steven Fisher


3 Answers

Use UITableView's heightForRowAtIndexPath :

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
 {
   int topPadding = 10;
   int bottomPadding = 10;
   float landscapeWidth = 400;
   float portraitWidth = 300;

   UIFont *font = [UIFont fontWithName:@"Arial" size:22];

   //This is for first cell only if you want for all then remove below condition
   if (indexPath.row == 0) // for cell with dynamic height
   {
      NSString *strText = [[arrTexts objectAtIndex:indexPath.row]; // filling text in label  
     if(landscape)//depends on orientation
     {
       CGSize maximumSize = CGSizeMake(landscapeWidth, MAXFLOAT); // change width and height to your requirement
     }
     else //protrait
     {
       CGSize maximumSize = CGSizeMake(portraitWidth, MAXFLOAT); // change width and height to your requirement
     }

     //dynamic height of string depending on given width to fit
     CGSize textSize = CGSizeZero;
     if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")
     {
        NSMutableParagraphStyle *pstyle = [NSMutableParagraphStyle new];
        pstyle.lineBreakMode = NSLineBreakByWordWrapping;

        textSize = [[strText boundingRectWithSize:CGSizeMake(width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName :font,NSParagraphStyleAttributeName:[pstyle copy]} context:nil] size];
     }
     else // < (iOS 7.0)
     {
        textSize = [strText sizeWithFont:font constrainedToSize:maximumSize lineBreakMode:NSLineBreakByWordWrapping] 
     }

     return (topPadding+textSize.height+bottomPadding) // caculate on your bases as u have string height
   }
   else
   {
       // return height from the storyboard
       return [super tableView:tableView heightForRowAtIndexPath:indexPath];
   }
 }

EDIT : Added for support for > and < ios7 and as sizeWithFont method is deprecated in iOS 7.0

like image 105
Paresh Navadiya Avatar answered Nov 20 '22 05:11

Paresh Navadiya


I've had success with a little simpler implementation. As long as your static table view has proper constraints on the cells, you can ask the system to size it for you:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
    let cell = self.tableView(self.tableView, cellForRowAtIndexPath: indexPath)
    let height = ceil(cell.systemLayoutSizeFittingSize(CGSizeMake(self.tableView.bounds.size.width, 1), withHorizontalFittingPriority: 1000, verticalFittingPriority: 1).height)
    return height
}
like image 45
Aaron Scherbing Avatar answered Nov 20 '22 07:11

Aaron Scherbing


I have gotten this to work using proper constraints where the label has top and bottom constraints set and returning the UITableViewAutomaticDimension in the heightForRowAt like this

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

In my case I had several labels inside a stack view and I had to set the stack view top and bottom to the contentView in order for the cell to grow.

like image 1
Maria Avatar answered Nov 20 '22 05:11

Maria