UITableView: Automatic Row Height

automatic row height

UITableView is definitely one of the most important UI components, and you can find it in almost every app. Very often the content is dynamic – and so is the length of the content. In this case you need table view cells, that have different sizes. You could calculate these sizes manually, but that’s a little bit cumbersome. Instead, you can use automatic row height.

Hint: This post is using Swift 3, Xcode 8 and iOS 10

Video


Implementing automatic row height

First, you have to use auto layout and elements that have an intrinsic content size. For example, that’s the case for a label. So let’s drag and drop a label inside a table view cell and set constraints for top, bottom, left and right margin to the container:

As you can see, there is no height constraint for the label. We don’t want this because the height is dynamic and the label calculates the height on itself – also called intrinsic content size. In order for the label to do that, it has to use as many lines as necessary. For that, we set the number of lines to 0 and use “word wrap” as line break mode:

Now there are just two things left: We have to set the row height to automatic and also specify an estimated row height. For that, we can set these properties in the corresponding view controller:

override func viewDidLoad() {
     super.viewDidLoad()

     tableView.rowHeight = UITableViewAutomaticDimension
     tableView.estimatedRowHeight = 44        
}

Does it work?

Now we can configure the whole view controller. It could look like this:

import UIKit

class TableViewController: UITableViewController {
    
    private var exampleContent = ["This is a short text.", "This is another text, and it is a little bit longer.", "Wow, this text is really very very long! I hope it can be read completely! Luckily, we are using automatic row height!"]
    

    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.contentInset = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)

        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 44
        
        tableView.reloadData()
        
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return exampleContent.count
    }

    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCellIdentifier", for: indexPath) as! TableViewCell
        
        let content = exampleContent[indexPath.row]
        
        cell.customLabel.text = content


        return cell
    }
}

Don’t forget to also create a custom table view cell and set the outlet for the label!

And indeed, we get the desired result:

References

Title image: @ Christopher Titze / shutterstock.com

1 comment

  1. This logic is not working with Static Cells. Could you please suggest logic for Static cells.

Comments are closed.