Search code examples
fontsaccessibilityswiftuidynamic-type-feature

Does SwiftUI support alternate layouts by preferred font size?


Ideally, an iOS app uses font sizes that follow the user's system-wide font size setting. The topic is covered in a WWDC talk from 2017 called Building Apps with Dynamic Type.

In simple cases, you set a UIView's font using named styles like body, caption1, title, which vary in size depending on the user's settings.

In trickier cases, you need to write different auto-layout constraints for different font sizes. For example, horizontally stacked labels may need to become vertically stacked when the font is larger.

enter image description here

enter image description here

For this situation, the WWDC talk shows some code like this:

if traitCollection.preferredContentSizeCategory > .extraExtraLarge {
    NSLayoutConstraint.deactivate( horizontalConstraints )
    NSLayoutConstraint.activate( verticalConstraints )
} else {
    NSLayoutConstraint.deactivate( verticalConstraints )
    NSLayoutConstraint.activate( horizontalConstraints )
}

What is the equivalent to this in SwiftUI?


Solution

  • The closest I can think of would be something like that:

    struct ContentView: View {
    
        @Environment(\.sizeCategory) var sizeCategory: ContentSizeCategory
    
        let largeSizeCategories: [ContentSizeCategory] = [.extraExtraLarge,
                                                          .extraExtraExtraLarge,
                                                          .accessibilityMedium,
                                                          .accessibilityLarge,
                                                          .accessibilityExtraLarge,
                                                          .accessibilityExtraExtraLarge,
                                                          .accessibilityExtraExtraExtraLarge]
    
        var body: some View {
            Group {
                if largeSizeCategories.contains(sizeCategory) {
                    VStack {
                        Text("Pizza, bananas, donuts")
                        Text("Io, Europa, Ganymede")
                    }
                } else {
                    HStack {
                        Text("Pizza, bananas, donuts")
                        Text("Io, Europa, Ganymede")
                    }
                }
            }
        }
    
    }
    

    Get the ContentSizeCategory from the Environment and adjust your view depending on the value.