How To Enable Dynamic Row Heights With UITableViews On iOS 8 And Later
One of the rather annoying things of developing native iOS apps has always been a relatively common task: Displaying data with a varying size in UITableViews. Since iOS 8 it is easier than ever before – once you know the trick.
Let's say you want to display a set of articles in a controller, each with its title and caption with a variabel length. Given that requirement of the variabel length, it's not possible to use any of the default UITableViewCell configurations (Subtitle would fit if you can ensure that title and caption fit in one line each).
Instead you have to create your own cell with its own labels that fit the requirements (the caption's label's Lines property has to be set to 0, so it can display multiple lines). In previous versions of iOS you then had to measure manually the final size of the cell's content so you could tell the table view in it's data source object how high each cell was. With iOS 8, that's not necessary anymore.
Setting Up The Table View
The first step is to tell your table view, that it should calculate the height of each row automatically. Second, provide an estimate on how the average height will be – so calculations become more accurate. That can be done in a two-liner:
TableView.RowHeight = UITableView.AutomaticDimension; TableView.EstimatedRowHeight = 60;
Setting Up The Cell
In my example I will use a storyboard with a UITableView control and a dynamic prototype cell. But I guess the same rules apply to Xib's as well (didn't try it yet).
Set the style of your prototype cell to custom, so you can add whatever labels and other contents (for example image views) you want to. In this example I am going to add a title and a text label. As written above, the text label's lines property has to be set to 0, so it isn't limited to a single line.
The Secret Sauce: Constraints
To leverage Auto Layout, you need to make sure you add vertical constraints. The title label needs a Vertical Space Constraint to it's super view – which is always the content view of the cell, not the cell itself!. The title label, which is then displaying the varying amount of text and therefore will have a dynamic height, needs to know it's top position, too, and it's distance to the bottom. So you need two additional Vertical Space Constraints here, the first from the text's top to the title's bottom (that will always be title.Y + title.Height), the second from the text's bottom to the super views's bottom.
You can easily add constraints with XCode's Interface Builder. Make sure to uncheck the "Constrain to margins" options, before you set anything. And if IB won't add a constrain because the value you type in is already set, change it to another number and then add it again.
An Example Project With Xamarin.iOS
I put a demo project on GitHub, which I created with Xamarin.iOS 8.10 and Xcode 6.3.
What do you think? Drop me a line and let me know!