2015-02-01 Layout of a tableviewcell depending upon device orientation

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)")
		}
	}

Result:
layout uitableviewcell depending upon device orientation.gif

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.