Coder Social home page Coder Social logo

mindgrub / swash Goto Github PK

View Code? Open in Web Editor NEW
74.0 3.0 2.0 553 KB

Fonts in iOS made safe, expressive, and dynamic.

License: MIT License

Ruby 3.08% Swift 95.63% Objective-C 1.29%
ios swift cocoapods fonts font uifont accessibility carthage custom-fonts dynamic

swash's Introduction

Swash

Version Swift 5.1 Platforms Carthage compatible License

Swash is a simple, safe, and expressive abstraction of UIFont with baked-in support for dynamic type.

Usage

To define a custom font, just create a String enum that conforms to the Font protocol.

enum Papyrus: String, Font {
    case regular = "Papyrus"
    case condensed = "Papyrus-Condensed"
}

That's all you need to start using your font in your project!

Static Sizes

label.font = Papyrus.regular.of(size: 17)

Dynamic Type (iOS 11+)

Uses UIFontMetrics for scaling. Setting adjustsFontForContentSizeCategory to true tells the label to automatically update the font when the user changes their content size preference. See our blog post for guidance on choosing default sizes for text styles, or just use Swash's provided defaults pulled from Apple's Human Interface Guidelines for iOS, watchOS, and tvOS.

label1.adjustsFontForContentSizeCategory = true
label2.adjustsFontForContentSizeCategory = true

label1.font = Papyrus.condensed.of(textStyle: .headline)
// Optional size cutoff and default size.
label2.font = GillSans.bold.of(textStyle: .title1, defaultSize: 28, maxSize: 38)

Dynamic Type Demo

Dynamic Type (Before iOS 11)

Uses system font scaling, no default size value. adjustsFontForContentSizeCategory requires the use of UIFontMetrics, so it is of no use for custom fonts before iOS 11. You'll have to update the fonts manually, either in traitCollectionDidChange(_:) or by observing the UIContentSizeCategoryDidChange notification.

label.font = Papyrus.condensed.of(style: .headline)
// Optional size cutoff
label.font = GillSans.bold.of(style: .title1, maxSize: 30)

System Font

You can use SystemFont to support dynamic type for different weights and further unify the font syntax in your project.

label1.font = SystemFont.light.of(size: 17)
label2.adjustsFontForContentSizeCategory = true
label2.font = SystemFont.preferred.of(textStyle: .body)
label3.font = SystemFont.semiboldItalic.of(textStyle: .body, maxSize: 30)

Important note: adjustsFontForContentSizeCategory only works with SystemFont for the preferred weight with a nil maxSize value. In any other case, you will need to update the font either in traitCollectionDidChange(_:) or by observing the UIContentSizeCategoryDidChange notification. This is because the preferred weight directly returns the result of UIFont.preferredFont(forTextStyle:).

Bold Text Device Setting

You can implement the boldTextMapping property on any Font in order to support the "Bold Text" device setting on iOS and tvOS.

var boldTextMapping: MyFont {
    switch self {
    case .regular: return .bold
    case .bold: return .black
    case .black: return self
    }
}

Now every regular MyFont instance will become bold if the user has "Bold Text" turned on in their device settings.

If you'd like, you can observe UIAccessibility.boldTextStatusDidChangeNotification via NotificationCenter and set your fonts when that updates.

Font Cascading

You can implement the static cascadeList property on any Font in order to support font cascading. In the event that your font does not support a character that is used in a label, this list will provide fallback fonts to use.

enum Papyrus: String, Font {
    case condensed = "Papyrus-Condensed"
    case regular = "Papyrus"
    
    var cascadeList: [CascadingFontProperties] {
        [.init(Damascus.regular)]
    }
}

Papyrus does not support Arabic characters. So, here we've provided Damascus as a fallback. If no fallback is provided, the system font will be used for unsupported characters.

Generate Boilerplate

Swash can attempt to log your font boilerplate for you!

Swash.logBoilerplate(forFontsWithFamilyNamesContaining: "gill")

Output:

enum GillSans: String, Font {
    case GillSans-Italic = "GillSans-Italic"
    case GillSans-SemiBold = "GillSans-SemiBold"
    case GillSans-UltraBold = "GillSans-UltraBold"
    case GillSans-Light = "GillSans-Light"
    case GillSans-Bold = "GillSans-Bold"
    case GillSans = "GillSans"
    case GillSans-SemiBoldItalic = "GillSans-SemiBoldItalic"
    case GillSans-BoldItalic = "GillSans-BoldItalic"
    case GillSans-LightItalic = "GillSans-LightItalic"
}

Just copy-paste the output into your project. You'll probably still need to doctor the case names a bit.

Debug Crashing

If your custom font fails to initialize, assertionFailure(_:file:line:) is called. This will crash debug builds with the default -Onone compiler optimization set. This is to help identify failed font initializations which can otherwise be hard to catch. Release builds with higher optimization levels will NOT crash, so you don't have to worry about your app crashing in production over a silly font.

Installation

CocoaPods

pod 'Swash'

Carthage

github "Mindgrub/Swash"

Make sure to specify your platform when you update (e.g. carthage update --platform iOS). Otherwise all 3 frameworks (iOS, tvOS, and watchOS) will be added.

License

Swash is available under the MIT license. See the LICENSE file for more info.

swash's People

Contributors

samhfrancis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

swash's Issues

UIFontDescriptor for cascade fonts

Hi Sam,
I have a need to use a UIFontDescriptor now to make a cascade list of fonts. My need is that I have a custom font (working great with Swash) but that font does not support Cyrillic, so I need to use a different custom font to fall back on, using a UIFontDescriptor. My question in detail and the answer for it are at this Stack Overflow:
https://stackoverflow.com/questions/59309023/ios-using-custom-arabic-cyrillic-fonts-automatically
I'm wondering if there is a way to easily encapsulate code like that or how to use it with Swash efficiently.
Thanks! Chris

Font sizes spreadsheet

Hi Sam, do you have a spreadsheet of the iOS font sizes for each style? Apple does not appear to have it on their site, or its hard to find. I like the graphs on your blog about Swash, easy to understand! But would be helpful to know all the size ramps, if I override a font size that I can know how each size goes up.
This page has a link but it doesn't seem to exist there at the destination. https://developer.apple.com/design/human-interface-guidelines/watchos/visual-design/typography/
Thank you.

Bold system setting support?

Do you think you will add support to gracefully handle isBoldTextEnabled or boldTextStatusDidChangeNotification? So we can map SomeFontRegular to SomeFontSemiBold or SomeFontBold

BTW Swash looks awesome. Going to try it in our app soon.

SwiftUI support

SwiftUI doesn't treat UIFonts like its own SwiftUI Font class, so by default using the same paradigm of the pod doesn't work. Would be great to have baked-in SUI support that can use the same syntax as before.

BTW, I love Swash and has made it easy to use in new AccuWeather app. ๐Ÿคฉ

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.