9

I am new to iOS development. I have a problem with my cell sizing. I am not using Auto-Laylout feature. My current TableView cell looks something like this. I want to make the label size which is selected in the image to be extended dynamically based on the text content of that Label.

Thanks in advance.

Kalai Arasi
  • 249
  • 1
  • 6
  • 16
  • 1
    check [this](http://stackoverflow.com/questions/19215199/dynamically-size-uitableviewcell-according-to-uilabel-with-paragraph-spacing). It's Objctive-C version – Elliot Li May 08 '15 at 01:50
  • @Boyi Li, I am sorry I have no idea about Objective C, please help... – Kalai Arasi May 08 '15 at 01:51
  • It can be done with 2 lines of code if you use auto layout. Why aren't you using that? – rdelmar May 08 '15 at 01:53
  • I have nearly 20 screens in my storyboard and if I use auto-layout for this screen alone, it affects the layout of all my other screens. Can you please say how to use auto-layout in this view alone ? – Kalai Arasi May 08 '15 at 01:54
  • You really should be using auto layout for all your screens. Enabling auto layout is a storyboard wide thing; it's either on or off for the whole storyboard. However, you could design your cell in a xib, and use auto layout there. – rdelmar May 08 '15 at 01:57
  • Sorry sir, I cant make changes to all my screens... Please help me... – Kalai Arasi May 08 '15 at 01:59
  • You want to extend height of the label if more text coming? – Amit89 May 08 '15 at 02:34
  • ya the height of the label should increase and so, the corresponding cell should also expand to hold that label size. – Kalai Arasi May 08 '15 at 02:40
  • Basically if you choose to not use autolayout, you won't be able to do this. Autolayout can be local to your tableView, but you need it to be iOS 8 to support autosizing. If you don't have any of this, it will be very very challenging (almost impossible) to implement this. – Schemetrical May 08 '15 at 05:03

4 Answers4

14

i think the swift version like below, it calculates nearer values not the exact height, for example

class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {

 var messageArray:[String] = []
 override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
      messageArray = ["One of the most interesting features of Newsstand is that once an asset downloading has started it will continue even if the application is suspended (that is: not running but still in memory) or it is terminated. Of course during while your app is suspended it will not receive any status update but it will be woken up in the background",
                      "In case that app has been terminated while downloading was in progress, the situation is different. Infact in the event of a finished downloading the app can not be simply woken up and the connection delegate finish download method called, as when an app is terminated its App delegate object doesn’t exist anymore. In such case the system will relaunch the app in the background.",
                      " If defined, this key will contain the array of all asset identifiers that caused the launch. From my tests it doesn’t seem this check is really required if you reconnect the pending downloading as explained in the next paragraph.",
                      "Whale&W",
                      "Rcokey",
                      "Punch",
                      "See & Dive"]
}

in the above we have an array which contains string of different length

 func numberOfSectionsInTableView(tableView: UITableView) -> Int
    {
        return 1;
    }

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    return messageArray.count;
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("CELL") as? UITableViewCell;
    if(cell == nil)
    {
        cell = UITableViewCell(style:UITableViewCellStyle.default, reuseIdentifier: "CELL")
        cell?.selectionStyle = UITableViewCellSelectionStyle.none
    }
    cell?.textLabel.font = UIFont.systemFontOfSize(15.0)
    cell?.textLabel.sizeToFit()
    cell?.textLabel.text = messageArray[indexPath.row]
    cell?.textLabel.numberOfLines = 0
    return cell!;
}

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
    var height:CGFloat = self.calculateHeightForString(messageArray[indexPath.row])
    return height + 70.0
}

func calculateHeight(inString:String) -> CGFloat
{
    let messageString = inString
    let attributes : [String : Any] = [NSFontAttributeName : UIFont.systemFont(ofSize: 15.0)]

    let attributedString : NSAttributedString = NSAttributedString(string: messageString, attributes: attributes)

    let rect : CGRect = attributedString.boundingRect(with: CGSize(width: 222.0, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)

    let requredSize:CGRect = rect
    return requredSize.height
}

try it in a new project just add the tableview and set its datasource and delegate and past the code above and run

the result will be like below

enter image description here

Shankar BS
  • 8,394
  • 6
  • 41
  • 53
  • all cells turn into short size and there is no other difference. All the contents are like merged. – Kalai Arasi May 08 '15 at 06:23
  • did u tried above code in separate project, .. u need to make some modification for your requirement, above code is just to find height based on the string content . i will add screen shot how s the result – Shankar BS May 08 '15 at 06:41
  • 1
    perhaps not the best approach. but the only one that did it for me – David Seek May 11 '17 at 13:57
6

Try to override methods:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

Complete solution:

In iOS 8, Apple introduces a new feature for UITableView known as Self Sizing Cells. Prior to iOS 8, if you displayed dynamic content in table view with varied row, you need to calculate the row height on your own.

In summary, here are the steps to implement when using self sizing cells:

• Add auto layout constraints in your prototype cell

• Specify the estimatedRowHeight of your table view

• Set the rowHeight of your table view to UITableViewAutomaticDimension

Expressing last two points in code, its look like:

tableView.estimatedRowHeight = 43.0;
tableView.rowHeight = UITableViewAutomaticDimension

You should add it in viewDidLoad method.

With just two lines of code, you instruct the table view to calculate the cell’s size matching its content and render it dynamically. This self sizing cell feature should save you tons of code and time.

In Attributes Inspector of your UILabel, change Lines value to 0, so label will automatically adjust the number of lines to fit the content.

Please note that first point is required and remember that you cannot use self sizing cell without applying auto layout.

If you are note familiar with auto layout, please read this, it will be enough:

https://developer.apple.com/library/mac/recipes/xcode_help-IB_auto_layout/chapters/pin-constraints.html

Or, easier way to set auto layout, but maybe not be what you exactly expected is to clear all of your constraints, go to Resolve Auto Layout Issues and for All Views click on Reset to Suggested Constraints.

stakahop
  • 921
  • 9
  • 18
  • 1
    I had it all right but was missing this "In Attributes Inspector of your UILabel, change Lines value to 0, so label will automatically adjust the number of lines to fit the content." from above. That did the trick. – neelabh Jul 09 '16 at 04:14
  • This made my day Thank you! – amar Sep 06 '17 at 12:22
2

Just add this in Viewdidload

tableView.estimatedRowHeight = 44.0 
tableView.rowHeight = UITableViewAutomaticDimension
Albi
  • 1,705
  • 1
  • 17
  • 28
2
func calculateHeight(inString:String) -> CGFloat
       {
           let messageString = inString
           let attributes : [NSAttributedString.Key : Any] = [NSAttributedString.Key(rawValue:
   NSAttributedString.Key.font.rawValue) : UIFont.systemFont(ofSize:
   15.0)]

           let attributedString : NSAttributedString = NSAttributedString(string: messageString, attributes: attributes)
           let rect : CGRect = attributedString.boundingRect(with: CGSize(width: 222.0, height: CGFloat.greatestFiniteMagnitude),
   options: .usesLineFragmentOrigin, context: nil)

           let requredSize:CGRect = rect
           return requredSize.height
       }
Srinivasan_iOS
  • 972
  • 10
  • 12