/Ampersand

Dynamic Type Support for Custom Fonts

Primary LanguageSwiftMIT LicenseMIT

GitHub license Carthage Compatible Platform

Ampersand is a small library that allows custom typefaces to be used seamlessly with the text styles API used by UIFont and UIFontDescriptor. This makes it simple to integrate a custom typeface in to your app whilst utilising the easy styling provided by the text style API.

Additionally, on iOS, Ampersand supports Dynamic Type for custom typefaces with no additional developer effort. This allows for a great accessibility experience even when not using the system default set of fonts.

Font Configuration

To use a custom typeface, first we must specify the font and point size we wish to use at the default font size for each of the text styles availabe, as well as which font should be used for each of the system font weights. This is achieved by providing a JSON configuration file describing the necessary attributes:

{
  "styles": [
    {
      "textStyle": "UICTFontTextStyleTitle0",
      "fontName": "Avenir-Medium",
      "pointSize": 30
    },
    {
      "textStyle": "UICTFontTextStyleTitle1",
      "fontName": "Avenir-Medium",
      "pointSize": 25
    },
    
  ],
  "weights": [
    {
      "fontWeight": "ultraLight",
      "fontName": "Avenir-Light"
    },
    {
      "fontWeight": "thin",
      "fontName": "Avenir-Light"
    },
    
  ]
}

A full example is provided for the Avenir typeface in the project's tests.

Registering an Application Font

Designating a custom typeface for use in your app involves passing the URL for your configuration file to an extension on UIFont:

let configurationURL = Bundle.main.url(forResource: "Avenir", withExtension: "json")!
UIFont.registerApplicationFont(withConfigurationAt: configurationURL)

This is the only setup that is required to register an "application font".

Using an Application Font

Once your typeface is registered as the application font it can be accessed using a set of extensions on UIFont that deliberately mirror the "preferred font" API used to access the system font:

let body = UIFont.applicationFont(forTextStyle: .body)
let nonScalingTitle = UIFont.nonScalingApplicationFont(forTextStyle: .title1)

You may also create instances of your appliction font for specific point sizes and weights:

let semibold = UIFont.applicationFont(ofSize: 17, weight: .semibold)

Extensions are also provided for UIFontDescriptor:

let body = UIFontDescriptor.applicationFontDescriptor(forTextStyle: .body)
let nonScalingTitle = UIFontDescriptor.nonScalingApplicationFontDescriptor(forTextStyle: .title1)

Using a FontProvider Directly

The FontProviding API is used internally to support the application font functionality of Ampersand, but can also be used directly if preferred. This may be useful when a certain section of your app requires a different typeface to be used. Creating a FontProvider is easy:

let configurationURL = Bundle.main.url(forResource: "Avenir", withExtension: "json")!
let fontProvider = FontProvider(configurationFileURL: configurationURL)

Fonts can then be created using text styles or sizes and weights:

let body = fontProvider.font(forTextStyle: .body)
let nonScalingTitle = fontProvider.nonScalingFont(forTextStyle: .title1)
let semibold = fontProvider.font(ofSize: 17, weight: .semibold)

Example Application with SPM Integration

An example application showing how to integrate Ampersand and use its Application Font APIs can be found here.