Make App Pie

Training for Developers and Artists

Use Dynamic Type

For reading ease and visual accessibility you should be using dynamic fonts whenever possible. Let’s look at an example you can get from the download files. I’ve run the Split View Controller from a previous tip in landscape on an iPad Pro 9.7 inch. Take a look at the labels on the table.

They are hard to read because they are so small. iOS has a system to make fonts bigger using dynamic type. Let’s look at a few issues with dynamic type programmatically. 

For the user, they need to change one setting to make this bigger. ON the iPad simulator, click the Home button, and Settings. Select General>Accessibility,

Then Larger Text

On the bottom is a slider which you can notch up for larger text. For even larger text you can click on the switch on top.  Make this pretty big.

That scales up the text in settings too. Go back to the app. You see bigger sizes but with white backgrounds,

The simulator has problems with this adjustment, which is why the white backgrounds. . Stop the app and re-run it.

By default, cells are dynamic text, the type called Body. Now rotate the simulator with a Command Left-Arrow, and drag out the master.  Depending on the device, you may see the text wrap or get cut off.

To make sure it wraps,   Head to the HueColorTableViewController and the cellForRowAtIndexpath method. Add the following line: 

cell?.textLabel?.numberOfLines = 0 

Setting the label property numberOfLines to 0 does two things: it allows for a variable number of lines and activates a word wrap mode. Run again, and  if you didn’t before, you’ll see our text wrap in the cells. 

I still have a static font for my detail label. Head over there and You’ll see I have a UIFont of 30-point American Typewriter. For dynamic type, You have two choices here. One is to use one of the system dynamic fonts. Add this to your code:

let dynamicFont = UIFont.preferredFont(forTextStyle: .title1)

The preferred Font method sets the font to the dynamic font title1. I’ll change the font to the dynamic font: 

colorLabel.font = dynamicFont

Run this

. This time, The font is a lot more visible, but on the system font. If I wanted a custom font, I’d have to do a few more steps. I’ll assign the colorLabel's font to  a class UIFontMetrics and its default, 

colorLabel.font = UIFontMetrics.default.scaledFont(for: font)

Finally, I need to tell the label to scale the font. 

colorLabel.adjustsFontForContentSizeCategory = true

To be sure we get word wrapping, I’ll do this again

 colorLabel.numberOfLines = 0

Run this. Change the font size to the smallest. 

You’ll see the label remains at 30 point, as the Master dynamic type in the cells shrink.

Now make the font as large as it can get and run again. The font scales.  

There is a complete course in the course library on accessibility which deep dives this topic and shows you the storyboard version of all this.  It is something you should check out for better accessibility and adaptability of your user interface.  

The Whole Code

Here’s the code for this week’s project. You can download the full project at Github.

HueColorTableViewController.swift

//
//  HueColorTableViewController.swift
//  ColorPicker
//
//
//  An exercise file for iOS Development Tips Weekly
//  by Steven Lipton (C)2018, All rights reserved
//  For videos go to http://bit.ly/TipsLinkedInLearning
//  For code go to http://bit.ly/AppPieGithub
//

import UIKit

protocol HueColorTableViewControllerDelegate{
    func didSelectColor(color:ColorEntry)
}


class HueColorTableViewController:UITableViewController{
    var delegate:HueColorTableViewControllerDelegate! = nil
    var colors:[ColorEntry] = ColorModel().hues(count: 12)
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return colors.count
    }
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell = tableView.dequeueReusableCell(withIdentifier: "cell")
        if cell == nil {
            cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
        }
        let row = indexPath.row
        cell?.contentView.backgroundColor = colors[row].color
        cell?.textLabel?.text = colors[row].name
        cell?.textLabel?.numberOfLines = 0
        return cell!
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let row = indexPath.row
        title = colors[row].name
        delegate.didSelectColor(color: colors[row])
    }
    
    override func loadView() {
        super.loadView()
    }
    

}

ColorDetailViewController.swift

//
// ColorDetailViewController.swift
// ColorPicker
//
//  An exercise file for iOS Development Tips Weekly
//  by Steven Lipton (C)2018, All rights reserved
//  For videos go to http://bit.ly/TipsLinkedInLearning
//  For code go to http://bit.ly/AppPieGithub
//

import UIKit

class ColorDetailViewController: UIViewController, HueColorTableViewControllerDelegate  {
    let colorLabel = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()
        addLayout()
        // Do any additional setup after loading the view.
    }
    
    //MARK:- Delegates
    func didSelectColor(color: ColorEntry) {
        view.backgroundColor = color.color
        colorLabel.text = color.name
    }
    
    //MARK:- Layout
    // All layout methods go here.
    func addLayout(){
        colorLabel.text = "Color Detail"
        let font = UIFont(name: "AmericanTypewriter", size: 30)!
       //let dynamicFont = UIFont.preferredFont(forTextStyle: .title1)
        colorLabel.font = UIFontMetrics.default.scaledFont(for: font)
        colorLabel.adjustsFontForContentSizeCategory = true
        colorLabel.numberOfLines = 0
        colorLabel.backgroundColor = .lightGray
        colorLabel.textAlignment = .center
        colorLabel.numberOfLines = 0
        view.addSubview(colorLabel)
        colorLabel.translatesAutoresizingMaskIntoConstraints = false
        var constraints = [NSLayoutConstraint]()
        constraints += [NSLayoutConstraint(item: colorLabel, attribute: .leading, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .leading, multiplier: 1.0, constant: 0)]
        constraints += [NSLayoutConstraint(item: colorLabel, attribute: .trailing, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .trailing, multiplier: 1.0, constant: 0)]
        constraints += [NSLayoutConstraint(item: colorLabel, attribute: .top, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .top, multiplier: 1.0, constant: 0)]
        constraints += [NSLayoutConstraint(item: colorLabel, attribute: .height, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .height, multiplier: 1 / 9, constant: 0)]
        view.addConstraints(constraints)
    }
}

ColorModel.swift

//
//  ColorModel.swift
//  ColorPicker
//
//
//  An exercise file for iOS Development Tips Weekly
//  by Steven Lipton (C)2018, All rights reserved
//  For videos go to http://bit.ly/TipsLinkedInLearning
//  For code go to http://bit.ly/AppPieGithub
//

import UIKit

class ColorEntry{
    var name:String = ""
    var color:UIColor
    var hue:CGFloat = 0.0
    var brightness:CGFloat = 0.5
    var saturation:CGFloat = 1.0
    
    init(name:String,color:UIColor){
        self.color = color
        self.name = name
    }
}


class ColorModel{
    var colors = [ColorEntry]()
    init(){
        colors = []
    }
    func hues(count:Int)->[ColorEntry]{
        colors = []
        if count <= 0 {return colors}
        for hue in 0...count{
            let hueValue = CGFloat(hue)/CGFloat(count)
            let color = UIColor(hue: hueValue, saturation: 1.0, brightness: 1.0, alpha: 1.0)
            let name = String(format:"H:%04.3f S:1.0 B:1.0 ",hueValue)
            let colorEntry = ColorEntry(name: name, color: color)
            colors += [colorEntry]
        }
        return colors
    }
    
    func lightnessScale(hue:UIColor,count:Int){
        
    }
    
}

One response to “Use Dynamic Type”

  1. […] been using the same code for the last few weeks. You can go to the last lesson to get everything but the changes made to ColorModel.swift, which is below. You can also download […]

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.