4

I’m creating a cross-platform app, iOS and macOS (not MacOS Catalyst), in SwiftUI.

I’m supporting Dynamic Type through the .font(.title) .font(.caption) etc. modifiers.

This works great on iOS, however MacOS doesn’t support Dynamic Type.

I know users can change the font size on their Mac system wide through the display settings, but I would like to add an app preference where users can change the font size only for my app. Something similar like, for example, the mail app offers (Format > Style > Bigger)

I’m quite an experienced iOS dev,but this is my first MacOS app and my first real SwiftUI-only app. I’ve searched google and SO for half a day but can not find a way to do this.

Can this be done? Perhaps there is some kind of modifier to scale the font with a factor (and I could make that factor a global variable that would increase or decrease by the user changing this setting), or perhaps there is another way?

1
  • I was thinking EnvironmentValue dynamicTypeSize, but the doc says: "On macOS, this value cannot be changed by users and does not affect the text size." Commented Jan 14, 2023 at 8:45

1 Answer 1

3

Here is an approach with a view modifier .dynamicFont that takes a factor.

Be aware that the standard sizes (for factor 1.0) reflect the standard macOS styles. You might cover iOS sizes as well there if you want to use it cross platform.

enter image description here

struct ContentView: View {
    var body: some View {

        HStack {
            GroupBox {
                VStack(alignment: .leading) {
                    
                    Text("Hello, World!")
                        .font(.title)
                    
                    Text("Hello, World!")
                        .font(.body)
                    
                    Text("Hello, World!")
                        .font(.caption)
                }
            }
            
            // example use
            GroupBox {
                VStack(alignment: .leading) {
                    
                    Text("Hello, World!")
                        .dynamicFont(.title, factor: 1.2)
                    
                    Text("Hello, World!")
                        .dynamicFont(.body, factor: 1.2)
                    
                    Text("Hello, World!")
                        .dynamicFont(.caption, factor: 1.2)
                }
            }
        }
    }
}




enum DynamicFontStyle {
    case largeTitle
    case title
    case headline
    case body
    case caption
    // ...
    
    // the standard sizes and weights are for MacOS!! and taken from
    // https://developer.apple.com/design/human-interface-guidelines/foundations/typography/#specifications
    
    func specs(factor: Double) -> Font {
        switch self {
        case .largeTitle:
            return Font.system(size: 26 * factor, weight: .regular)
        case .title:
            return Font.system(size: 22 * factor, weight: .regular)
        case .headline:
            return Font.system(size: 13 * factor, weight: .bold)
        case .body:
            return Font.system(size: 13 * factor, weight: .regular)
        case .caption:
            return Font.system(size: 10  * factor, weight: .regular)
        }
        // ...
    }
}


// View expension for ease of use
extension View {
    func dynamicFont(_ style: DynamicFontStyle = .body, factor: Double = 1) -> some View {
        self
            .modifier(DynamicFontModifier(style: style, factor: factor))
    }
}


// View Modifier
struct DynamicFontModifier: ViewModifier  {
    
    let style: DynamicFontStyle
    let factor: Double
    
    func body(content: Content) -> some View {
        content
            .font(style.specs(factor: factor))
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

This looks great. Let me give this a try on Monday. Will report back and upvote etc if this work!! Thank you so much in advance!!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.