-
-
Save loganmoseley/38197bd8556ba3578a336f7d9144a933 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
import UIKit | |
enum ScalableFont { | |
case system(size: CGFloat, weight: Font.Weight = .regular, design: Font.Design = .default) | |
case custom(_ name: String, size: CGFloat) | |
var size: CGFloat { | |
switch self { | |
case let .system(size: size, weight: _, design: _): | |
return size | |
case let .custom(_, size: size): | |
return size | |
} | |
} | |
func makeFont(withScaledSize scaledSize: CGFloat) -> Font { | |
switch self { | |
case let .system(size: _, weight: weight, design: design): | |
return .system(size: scaledSize, weight: weight, design: design) | |
case let .custom(name, size: _): | |
return .custom(name, size: scaledSize) | |
} | |
} | |
} | |
struct ScaledFontModifier: ViewModifier { | |
@Environment(\.sizeCategory) var sizeCategory | |
var scalableFont: ScalableFont | |
func body(content: Content) -> some View { | |
let sizedTraits = UITraitCollection(preferredContentSizeCategory: sizeCategory.asUIContentSizeCategory) | |
let scaledSize = UIFontMetrics.default.scaledValue(for: scalableFont.size, compatibleWith: sizedTraits) | |
return content.font(scalableFont.makeFont(withScaledSize: scaledSize)) | |
} | |
} | |
extension View { | |
func scalableFont(_ scalableFont: ScalableFont) -> some View { | |
return self.modifier(ScaledFontModifier(scalableFont: scalableFont)) | |
} | |
} | |
extension ContentSizeCategory { | |
var asUIContentSizeCategory: UIContentSizeCategory { | |
switch self { | |
case .extraSmall: return .extraSmall | |
case .small: return .small | |
case .medium: return .medium | |
case .large: return .large | |
case .extraLarge: return .extraLarge | |
case .extraExtraLarge: return .extraExtraLarge | |
case .extraExtraExtraLarge: return .extraExtraExtraLarge | |
case .accessibilityMedium: return .accessibilityMedium | |
case .accessibilityLarge: return .accessibilityLarge | |
case .accessibilityExtraLarge: return .accessibilityExtraLarge | |
case .accessibilityExtraExtraLarge: return .accessibilityExtraExtraLarge | |
case .accessibilityExtraExtraExtraLarge: return .accessibilityExtraExtraExtraLarge | |
@unknown default: return .large // The default Dynamic Type size. | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Forked from Soroush’s to play nicely in SwiftUI Previews, where
UIFontMetrics
cannot see SwiftUI-environment overrides. Instead of lettingUIFontMetrics
read the ambientUIContentSizeCategory
, we make it calculate based on the SwiftUI value.Upshot: You can make a group of previews that show your UI at different font sizes, which will work in a running app!