Last week, a refresh of the design of my client's app called for a layout that changed depending on the device orientation. We're using AutoLayout and didn't want to use any deprecated methods.
Problem was that it called for layout changes within a UITableViewCell. I thought of a way to do this with AutoLayout but the constraints would become quite complex. Instead, I took the following approach:
Thus the UITableViewCell subclass looks as follows:
class CustomTableCell : UITableViewCell { @IBOutlet weak var dateLabel: UILabel! @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var trailingConstraint: NSLayoutConstraint! }
Problem is: where can you set properties all the currently visible cells? The easiest way I could come up with, is in the cellForRowAtIndexPath() function. The view controller class has the following property:
var size: CGSize = CGSizeZero
The viewWillTransitionToSize() function stores the new screen size and asks the UITableView to reload:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) self.size = size NSLog("viewWillTransitionToSize self.size = \(self.size)") self.tableView!.reloadData() }
And when dequeueing new cells, we set the constraint its constant:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("TestCell") as CustomTableCell! NSLog("self.size=\(self.size)") cell.nameLabel.text = self.items[indexPath.row] if self.size.width > self.size.height { //Landscape NSLog("Landscape") cell.trailingConstraint.constant = 100 } else { //Portrait NSLog("Portrait") cell.trailingConstraint.constant = 0 } return cell }
Because viewWillTransitionToSize() is not called when the View Controller is run for the first time, I also added the following code to viewWillLayoutSubviews():
override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() // Only run once, upon first display if self.size == CGSizeZero { self.size = self.tableView!.frame.size NSLog("viewWillLayoutSubviews self.size = \(self.size)") } }
Download the example project: TestTableViewCellSizing.zip
Note: I created the above truly breathtaking animated gif by taking a screen recording with QuickTime Player, running the iOS Simulator, then converting the resulting .mov file with the following ffmpeg command:
ffmpeg -i example.mov -r 15 example.gif
ffpmeg was installed via Homebrew.