Reputation: 5625
In SwiftUI you get all these handy little Font convenience accessors like Font.caption
, Font.title
, Font.body
, etc..
e.g.
VStack {
Text("Some Title").font(Font.title)
Text("Some Caption Text").font(Font.caption)
}
They all specify different font styles for the default Helvetica font family. I'd like to use these very helpful convenience accessors without ever using Helvetica in my app. Can I change the default font family? Or do I constantly have to apply custom fonts like e.g.:
Text("Custom Text").font(Font.custom("SourceSansPro-Regular", size: 14.0)
Upvotes: 21
Views: 11800
Reputation: 47
Here's an approach that combines some of these methods, specifically Justin's approach and Brady Murphy's Medium Article. The idea is to create a font manager that can be incorporated into a Font
extension to override the default. I wish there were a compiler directive that could skip the Font extension for Previews. This will still break previews.
This func used once will grab the actual font names:
// put the following into the .onAppear of a top level view or App.init
func getCustomFontNames() {
// get each of the font families
for family in UIFont.familyNames.sorted() {
let names = UIFont.fontNames(forFamilyName: family)
// print array of names
print("Family: \(family) Font names: \(names)")
}
}
Font manager that can create a default but also allows for multiple fonts by calling the font family struct directly.
typealias FMgr = FontManager
struct FontManager {
// dynamic font sizes
struct dynamicSize {
public static var largeTitle : CGFloat = UIFont.preferredFont(forTextStyle: .largeTitle).pointSize
public static var title : CGFloat = UIFont.preferredFont(forTextStyle: .title1).pointSize
// repeat for all the dynamic sizes
}
// App Supplied Fonts
struct Quicksand {
static let familyRoot = "Quicksand"
// weights
static let heavy = bold
static let bold = "\(familyRoot)-Bold"
static let semibold = "\(familyRoot)-SemiBold"
static let medium = regular
static let regular = "\(familyRoot)-Regular"
static let thin = light
static let light = "\(familyRoot)-Light"
static let ultralight = light
// dynamic sizes
static let largeTitle : Font = Font.custom(FMgr.Quicksand.bold, size: FMgr.dynamicSize.largeTitle)
// repeat for other sizes
}
// structs for other fonts
}
extension Font {
public static var largeTitle = FMgr.Quicksand.largeTitle
// repeat for the rest of the dynamic sizes
}
Upvotes: 2
Reputation: 1671
You can override the system font if you want.
extension Font {
/// Create a font with the large title text style.
public static var largeTitle: Font {
return Font.custom("OpenSans-Regular", size: UIFont.preferredFont(forTextStyle: .largeTitle).pointSize)
}
/// Create a font with the title text style.
public static var title: Font {
return Font.custom("OpenSans-Regular", size: UIFont.preferredFont(forTextStyle: .title1).pointSize)
}
/// Create a font with the headline text style.
public static var headline: Font {
return Font.custom("OpenSans-Regular", size: UIFont.preferredFont(forTextStyle: .headline).pointSize)
}
/// Create a font with the subheadline text style.
public static var subheadline: Font {
return Font.custom("OpenSans-Light", size: UIFont.preferredFont(forTextStyle: .subheadline).pointSize)
}
/// Create a font with the body text style.
public static var body: Font {
return Font.custom("OpenSans-Regular", size: UIFont.preferredFont(forTextStyle: .body).pointSize)
}
/// Create a font with the callout text style.
public static var callout: Font {
return Font.custom("OpenSans-Regular", size: UIFont.preferredFont(forTextStyle: .callout).pointSize)
}
/// Create a font with the footnote text style.
public static var footnote: Font {
return Font.custom("OpenSans-Regular", size: UIFont.preferredFont(forTextStyle: .footnote).pointSize)
}
/// Create a font with the caption text style.
public static var caption: Font {
return Font.custom("OpenSans-Regular", size: UIFont.preferredFont(forTextStyle: .caption1).pointSize)
}
public static func system(size: CGFloat, weight: Font.Weight = .regular, design: Font.Design = .default) -> Font {
var font = "OpenSans-Regular"
switch weight {
case .bold: font = "OpenSans-Bold"
case .heavy: font = "OpenSans-ExtraBold"
case .light: font = "OpenSans-Light"
case .medium: font = "OpenSans-Regular"
case .semibold: font = "OpenSans-SemiBold"
case .thin: font = "OpenSans-Light"
case .ultraLight: font = "OpenSans-Light"
default: break
}
return Font.custom(font, size: size)
}
}
Upvotes: 25
Reputation: 251
This is my approach:
struct Fonts {
static func oswaldRegular(size:CGFloat) -> Font{
return Font.custom("Oswald-Regular", size: size)
}
static func oswaldLight(size:CGFloat) -> Font{
return Font.custom("Oswald-Light", size: size)
}
static func oswaldBold(size:CGFloat) -> Font{
return Font.custom("Oswald-Bold", size: size)
}
}
Upvotes: 2
Reputation: 5625
My current approach is to just recreate my own font factory:
struct MyFont {
static let title = Font.custom("SourceSansPro-Bold", size: 24.0)
static let body = Font.custom("SourceSansPro-Regular", size: 12.0)
}
and then use e.g. MyFont.title
in place of Font.title
Upvotes: 11