How To Build An App Without Interface Builder – Part 7: Nicer Cell
Now let's make the table view cell nicer. First we need a patter image. I used Paintcode to generate this patter:
You can download the pattern images here. Put the three images into the assed catalog of the app. Now open BirthdayCell.swift and add the following property:
let patternView: UIView
In the initializer before the super.init call add the code:
patternView = UIView() patternView.translatesAutoresizingMaskIntoConstraints = false
This is needed because non optional properties need to be initialized when super.init is called.
Now set the patter as the background color of the patter view and add the it to the cell by adding the following code after the super.init call:
patternView.backgroundColor = UIColor(patternImage: UIImage(named: "cellBackgroundPattern")!) addSubview(patternView)
The pattern view needs some constraints. First we need to change the views to this:
let views = ["pattern": patternView, "name": nameLabel, "birthday": birthdayLabel]
Put the following code at the beginning of the constrains definition:
layoutConstraints += NSLayoutConstraint.constraintsWithVisualFormat("|[pattern]", options: [], metrics: nil, views: views) layoutConstraints += NSLayoutConstraint.constraintsWithVisualFormat("V:|[pattern]|", options: [], metrics: nil, views: views) layoutConstraints.append(patternView.trailingAnchor.constraintEqualToAnchor(trailingAnchor, constant: -80))
Build and run and add John Appleseed to the list. You should see something like this:
Hm, ok. The name isn't readable anymore. Add the following code to the setup of the name label:
nameLabel.font = .systemFontOfSize(30) nameLabel.textColor = .whiteColor()
Build and run again. Now it looks much better. But what if the progress has a value that the pattern is partly beneath the name and partly not. First let's figure out how big the problem is. Set the trailing constraint for the pattern view to -150:
layoutConstraints.append(patternView.trailingAnchor.constraintEqualToAnchor(trailingAnchor, constant: -150))
Build and run. You should see something like this:
Uh, thats bad. The name isn't readable because it's white text on a white background. We are going to change that.
First remove the line nameLabel.textColor = .whiteColor(). Then rearrange the addSubview calls that the order is like that:
addSubview(nameLabel) addSubview(birthdayLabel) addSubview(patternView)
With this change the patter background is above the name label. Build and run and add John to the list. You should see something like this:
Now add another label property:
let patternNameLabel: UILabel
Add within the initializer:
patternNameLabel = UILabel() patternNameLabel.translatesAutoresizingMaskIntoConstraints = false patternNameLabel.font = nameLabel.font patternNameLabel.textColor = .whiteColor()
Now add the label as a subview to the pattern view:
patternView.addSubview(patternNameLabel)
We need constraints for the new label. The constraints need to be in a way that the new label is at exact same position as the name label. Add these constraints:
layoutConstraints.append(patternNameLabel.leadingAnchor.constraintEqualToAnchor(nameLabel.leadingAnchor)) layoutConstraints.append(patternNameLabel.centerYAnchor.constraintEqualToAnchor(nameLabel.centerYAnchor))
These have been a lot changes. For completeness here is the table view cell class how it looks like after the changes:
import UIKit class BirthdayCell: UITableViewCell { let patternView: UIView let nameLabel: UILabel let patternNameLabel: UILabel let birthdayLabel: UILabel override init(style: UITableViewCellStyle, reuseIdentifier: String?) { patternView = UIView() patternView.translatesAutoresizingMaskIntoConstraints = false patternView.clipsToBounds = true nameLabel = UILabel() nameLabel.translatesAutoresizingMaskIntoConstraints = false nameLabel.font = .systemFontOfSize(30) patternNameLabel = UILabel() patternNameLabel.translatesAutoresizingMaskIntoConstraints = false patternNameLabel.font = nameLabel.font patternNameLabel.textColor = .whiteColor() birthdayLabel = UILabel() birthdayLabel.translatesAutoresizingMaskIntoConstraints = false super.init(style: style, reuseIdentifier: reuseIdentifier) patternView.backgroundColor = UIColor(patternImage: UIImage(named: "cellBackgroundPattern")!) addSubview(nameLabel) addSubview(birthdayLabel) addSubview(patternView) patternView.addSubview(patternNameLabel) let views = ["pattern": patternView, "name": nameLabel, "birthday": birthdayLabel] var layoutConstraints = [NSLayoutConstraint]() layoutConstraints += NSLayoutConstraint.constraintsWithVisualFormat("|[pattern]", options: [], metrics: nil, views: views) layoutConstraints += NSLayoutConstraint.constraintsWithVisualFormat("V:|[pattern]|", options: [], metrics: nil, views: views) layoutConstraints.append(patternView.trailingAnchor.constraintEqualToAnchor(trailingAnchor, constant: -150)) layoutConstraints.append(nameLabel.centerXAnchor.constraintEqualToAnchor(centerXAnchor)) layoutConstraints.append(nameLabel.centerYAnchor.constraintEqualToAnchor(centerYAnchor)) layoutConstraints += NSLayoutConstraint.constraintsWithVisualFormat("[birthday]-|", options: [], metrics: nil, views: views) layoutConstraints += NSLayoutConstraint.constraintsWithVisualFormat("V:[birthday]|", options: [], metrics: nil, views: views) layoutConstraints.append(patternNameLabel.leadingAnchor.constraintEqualToAnchor(nameLabel.leadingAnchor)) layoutConstraints.append(patternNameLabel.centerYAnchor.constraintEqualToAnchor(nameLabel.centerYAnchor)) NSLayoutConstraint.activateConstraints(layoutConstraints) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
The last thing we need to do is to set the name to the patter name label. Open BirthdaysListDataProvider.swift and add the following line in cellForRowAtIndexPath:
cell.patternNameLabel.text = birthday.firstName
Now let's see the result. Build and run and add John. You should see something like this:
Nice. This is a much nicer cell. It's not perfect yet. But this is enough for today. See you next time.
You can find the code on github.