【问题标题】:How to set a custom font family as the default for an entire app in SwiftUI如何在 SwiftUI 中将自定义字体系列设置为整个应用程序的默认字体
【发布时间】:2019-10-14 11:05:51
【问题描述】:

在 SwiftUI 中,您可以获得所有这些方便的小字体便利访问器,例如 Font.caption、Font.title、Font.body 等。

例如

VStack {
 Text("Some Title").font(Font.title)
 Text("Some Caption Text").font(Font.caption)
}

它们都为默认的 Helvetica 字体系列指定了不同的字体样式。我想使用这些非常有用的便利访问器,而无需在我的应用程序中使用 Helvetica。 我可以更改默认字体系列吗? 或者我是否必须经常应用自定义字体,例如:

Text("Custom Text").font(Font.custom("SourceSansPro-Regular", size: 14.0)

【问题讨论】:

    标签: ios swiftui


    【解决方案1】:

    您可以根据需要覆盖系统字体。

        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)
        }
    }
    

    【讨论】:

    • 这会导致 SwiftUI 实时预览在 Xcode 11.5 中崩溃。
    • 适用于Text 等常规元素,但不适用于Section 标头或navigationBarTitle,知道如何实现这一点吗?
    • 这会使 Xcode 13 中的 Preview 崩溃,并显示以下消息:replaced function 'system(size:weight:design:)' is not marked dynamic
    【解决方案2】:

    我目前的方法是重新创建自己的字体工厂:

    struct MyFont {
      static let title = Font.custom("SourceSansPro-Bold", size: 24.0)
      static let body = Font.custom("SourceSansPro-Regular", size: 12.0)
    }
    

    然后使用例如MyFont.title 代替 Font.title

    【讨论】:

      【解决方案3】:

      这是我的方法:

      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)
          }
      
      }
      

      【讨论】:

      • 我可以在 info.plist 中添加自定义字体吗?
      • 是的。它是假的。
      【解决方案4】:

      这是一种结合了其中一些方法的方法,特别是 Justin 的方法和 Brady Murphy 的 Medium 文章。这个想法是创建一个字体管理器,可以合并到Font 扩展中以覆盖默认值。我希望有一个编译器指令可以跳过预览的字体扩展。这仍然会中断预览。

      这个函数使用一次将获取实际的字体名称:

      // 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)")
          }
      }
      

      字体管理器可以创建默认字体,但也允许通过直接调用字体系列结构来使用多种字体。

      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
      }
      

      【讨论】:

        猜你喜欢
        • 2018-03-24
        • 1970-01-01
        • 2013-04-30
        • 2018-05-21
        • 2013-11-01
        • 2012-02-01
        • 2011-11-28
        • 2021-10-07
        相关资源
        最近更新 更多