Reputation: 7668
I'm trying to change the default font in SwiftUI for every view in my app.
What I want to avoid is to set it every time like so:
.font(.custom("FONT_NAME", size: 20))
What I want is to change it just one time for all Text views, and most important, I would like to keep using the modifiers:
.font(.caption)
without resetting the Text view to the system font.
But still I didn't find any solution, does anyone have one?
Upvotes: 9
Views: 6838
Reputation: 1225
You can use a view modifier to solve your case.
@available(iOS 13.0, *)
struct CustomText: ViewModifier {
func body(content: Content) -> some View {
content
.font(.custom("FONT_NAME", size: textSize(textStyle: .headline)))
.background(Color.blue)
.foregroundColor(Color.white)
//Other customization
}
}
//For Accessibility feature
func textSize(textStyle: UIFont.TextStyle) -> CGFloat {
return UIFont.preferredFont(forTextStyle: textStyle).pointSize
}
@available(iOS 13.0, *)
struct ContentView: View {
var body: some View {
Text("Hello, SwiftUI")
.modifier(CustomText())
.font(.caption) // You can still change the font .
}
}
@available(iOS 13.0, *)
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Upvotes: 0
Reputation: 2738
You can build your own view modifier. You can define what size and font you want to use for each of the UIFont.TextStyle inside private var fontDescriptions:
.
Now you can call this modifier on you Views like this. Text("my text").customFont(.headline)
Keep in mind, this one also implements the font scaling feature.
You could also call your "customFont" function "font" if you want to be hardcore.
extension View {
func customFont(_ textStyle: UIFont.TextStyle) -> ModifiedContent<Self, CustomFont> {
return modifier(CustomFont(textStyle: textStyle))
}
}
struct CustomFont: ViewModifier {
let textStyle: UIFont.TextStyle
/// Will trigger the refresh of the view when the ContentSizeCategory changes.
@Environment(\.sizeCategory) var sizeCategory: ContentSizeCategory
func body(content: Content) -> some View {
guard let fontDescription = fontDescriptions[textStyle] else {
print("textStyle nicht vorhanden: \(textStyle)")
return content.font(.system(.body));
}
let fontMetrics = UIFontMetrics(forTextStyle: textStyle)
let fontSize = fontMetrics.scaledValue(for: fontDescription.1)
return content.font(.custom(fontDescription.0, size: fontSize))
}
}
/// Define the custom fonts to use, depending on the TextStyle.
typealias CustomFontDescription = (String, CGFloat)
private var fontDescriptions: [UIFont.TextStyle: CustomFontDescription] = [
.headline: ("MYFONT", SIZE),
.subheadline: ("MYFONT", SIZE),
...
]
Upvotes: 5