All Projects → kharrison → ScaledFont

kharrison / ScaledFont

Licence: BSD-3-Clause license
ScaledFont - Using custom fonts with dynamic type

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to ScaledFont

SwiftCurrent
A library for managing complex workflows in Swift
Stars: ✭ 286 (+472%)
Mutual labels:  tvos, watchos, swiftui
data-field
A SwiftUI view that wraps a text field to only accept specific data.
Stars: ✭ 13 (-74%)
Mutual labels:  tvos, watchos, swiftui
WWDCNotes
WWDCNotes.com content
Stars: ✭ 343 (+586%)
Mutual labels:  tvos, watchos, swiftui
Wwdc
You don't have the time to watch all the WWDC session videos yourself? No problem me and many contributors extracted the gist for you 🥳
Stars: ✭ 2,561 (+5022%)
Mutual labels:  tvos, watchos, swiftui
Columbus
A feature-rich country picker for iOS, tvOS and watchOS.
Stars: ✭ 23 (-54%)
Mutual labels:  tvos, watchos, swiftui
QuoteKit
A framework to use the free APIs provided by https://quotable.io
Stars: ✭ 17 (-66%)
Mutual labels:  tvos, watchos, swiftui
KeyboardKitPro
KeyboardKit Pro extends KeyboardKit with pro features.
Stars: ✭ 42 (-16%)
Mutual labels:  tvos, watchos, swiftui
Open Source Ios Apps
📱 Collaborative List of Open-Source iOS Apps
Stars: ✭ 28,826 (+57552%)
Mutual labels:  tvos, watchos, swiftui
stinsen
Coordinators in SwiftUI. Simple, powerful and elegant.
Stars: ✭ 563 (+1026%)
Mutual labels:  tvos, watchos, swiftui
IrregularGradient
Create animated irregular gradients in SwiftUI.
Stars: ✭ 127 (+154%)
Mutual labels:  tvos, watchos, swiftui
TermiNetwork
🌏 A zero-dependency networking solution for building modern and secure iOS, watchOS, macOS and tvOS applications.
Stars: ✭ 80 (+60%)
Mutual labels:  tvos, watchos, swiftui
Swiftui Kit
A SwiftUI system components and interactions demo app
Stars: ✭ 1,733 (+3366%)
Mutual labels:  tvos, watchos, swiftui
Swiftui Sliders
🚀 SwiftUI Sliders with custom styles
Stars: ✭ 241 (+382%)
Mutual labels:  tvos, watchos
Xamarin Macios
Bridges the worlds of .NET with the native APIs of macOS, iOS, tvOS, and watchOS.
Stars: ✭ 2,109 (+4118%)
Mutual labels:  tvos, watchos
Fire
🔥A delightful HTTP/HTTPS networking framework for iOS/macOS/watchOS/tvOS platforms written in Swift.
Stars: ✭ 243 (+386%)
Mutual labels:  tvos, watchos
Mirrordiffkit
Graduation from messy XCTAssertEqual messages.
Stars: ✭ 168 (+236%)
Mutual labels:  tvos, watchos
Cocoalumberjack
A fast & simple, yet powerful & flexible logging framework for Mac and iOS
Stars: ✭ 12,584 (+25068%)
Mutual labels:  tvos, watchos
Futures
Lightweight promises for iOS, macOS, tvOS, watchOS, and Linux
Stars: ✭ 59 (+18%)
Mutual labels:  tvos, watchos
Anydate
Swifty Date & Time API inspired from Java 8 DateTime API.
Stars: ✭ 178 (+256%)
Mutual labels:  tvos, watchos
Human Interface Guidelines Extras
Community additions to Apple's Human Interface Guidelines
Stars: ✭ 225 (+350%)
Mutual labels:  tvos, watchos

ScaledFont - Custom Fonts With Dynamic Type

A utility type to help you use custom fonts with dynamic type.

Dynamic type is an essential iOS feature that allows the user to choose their preferred text size. Fully supporting dynamic type with a custom font requires two things:

  1. Define a base font with a suitable font weight and size for each of the possible text styles at the Large (Default) content size.
  2. Scale the base font across the range of dynamic type content sizes.

For the first step, you might want to start with the typography section of the Apple Human Interface Guidelines for iOS which list the font metrics Apple uses for the default San Francisco font.

For example, here I'm creating a bold Noteworthy font at 17 points as the base headline font and a light version of the font for the base body font:

let headlineFont = UIFont(name: "Noteworthy-Bold", size: 17)
let bodyFont = UIFont(name: "Noteworthy-Light", size: 17)

For the second step, it's been possible since iOS 11 to scale a base font for the user's chosen dynamic type size using font metrics:

let headMetrics = UIFontMetrics(forTextStyle: .headline)
headlineLabel.font = headMetrics.scaledFont(for: headlineFont)

let bodyMetrics = UIFontMetrics(forTextStyle: .body)
bodyLabel.font = bodyMetrics.scaledFont(for: bodyFont)

The problem, if you do this for every text style you use, is that you end up with those font metrics spread all over your app. That's both difficult to maintain and hard to keep consistent when you want to make design changes.

TIP: Don't forget when using UIKit labels, text fields and text views to enable automatic adjustments when the user changes their preferred content size:

label.adjustsFontForContentSizeCategory = true

Style Dictionary

To make it easier to manage the base font metrics for all of the possible text styles the ScaledFont type collects them into a style dictionary. You store the style dictionary as a property list file that, by default, you include in the main bundle.

The style dictionary contains an entry for each text style. The available text styles are:

  • largeTitle, title, title2, title3
  • headline, subheadline, body, callout
  • footnote, caption, caption2

The value of each entry is a dictionary with two keys:

  • fontName: A String which is the font name.
  • fontSize: A number which is the point size to use at the .large (base) content size.

For example, to use a 17 pt Noteworthy-Bold font for the .headline style at the .large content size:

<dict>
  <key>headline</key>
  <dict>
    <key>fontName</key>
    <string>Noteworthy-Bold</string>
    <key>fontSize</key>
    <integer>17</integer>
  </dict>
</dict>

You do not need to include an entry for every text style but if you try to use a text style that is not included in the dictionary it will fallback to the system preferred font.

If you are not sure what font names to use you can print all available names with this code snippet:

let families = UIFont.familyNames
families.sorted().forEach {
  print("\($0)")
  let names = UIFont.fontNames(forFamilyName: $0)
  print(names)
}

Example Style Dictionaries

See the Examples folder included in this package for some examples. The Noteworthy style dictionary uses a built-in iOS font.

To use the NotoSerif example you'll need to download the font files from Google fonts, add them to your application target, and list them under "Fonts provided by application" in the Info.plist file of the target.

Check the license for any fonts you plan on shipping with your application.

Using A ScaledFont - UIKit

When using UIKit you apply the scaled font to the text label, text field or text view in code. You need a minimum deployment target of iOS 11 or later.

  1. Create the ScaledFont by specifying the name of the style dictionary. Add the style dictionary to the main bundle along with any custom fonts you are using:

    let scaledFont = ScaledFont(fontName: "Noteworthy")
  2. Use the font(forTextStyle:) method of the scaled font when setting the font of any text labels, fields or views:

    let label = UILabel()
    label.font = scaledFont.font(forTextStyle: .headline)
  3. Remember to set the adjustsFontFotContentSizeCategory property to have the font size adjust automatically when the user changes their preferred content size:

    label.adjustsFontForContentSizeCategory = true

Using A ScaledFont - SwiftUI

When using SwiftUI you create the scaled font and add it to the environment of a view. You then apply the scaled font using a view modifier to any view in the view hierarchy. You need a minimum deployment target of iOS 13 or later to use SwiftUI.

  1. Create the ScaledFont by specifying the name of the style dictionary. Add the style dictionary to the main bundle along with any custom fonts you are using:

    let scaledFont = ScaledFont(fontName: "Noteworthy")
  2. Apply the scaled font to the environment of a view. This might typically be the root view of your view hierarchy:

    ContentView()
    .environment(\.scaledFont, scaledFont)
  3. Apply the scaled font view modifier to a view containing text in the view hierarchy:

    Text("Headline")
    .scaledFont(.headline)

Note: A SwiftUI view presented in a sheet does not inherit the environment of the presenting view. If you want to use a scaled font in the presented view you will need to pass it in the environment:

struct ContentView: View {
  @Environment(\.scaledFont) private var scaledFont
  @State private var isShowingSheet = false
  
  var body: some View {
    Button("Present View") {
        isShowingSheet = true
    }
    .sheet(isPresented: $isShowingSheet) {
        SheetView()
        .environment(\.scaledFont, scaledFont)
    }
  }
}

Further Reading

The following blog posts on useyourloaf.com provide more details:

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].