Version Platforms SwiftUI Swift Package Manager Cocoapods

VFont

VFont 是一个出色的库,它简化了在 iOS 项目中使用可变字体的过程。

如果您从未听说过可变字体,我建议阅读这篇由 @romashamin 撰写的文章:现实生活中的可变字体:如何使用和喜爱它们

Sponsored by Evil Martians

这个库能简化什么?

首先,我想知道 iOS 是否支持可变字体。现在,开发者通常使用顶层的 UIFont 类来单独处理 Light、Regular、Medium、Bold 和其他字体样式。我发现 iOS 3.2 已经添加了 VF 支持。然而,它是在 CoreText 库的 CTFont 类中使用底层代码实现的。这导致需要额外的工作才能使用 CoreTextUIFont 来访问可变字体。

用法

首先,您需要将自定义可变字体添加到您的项目中。如果您从未这样做过,我建议阅读这篇教程

❗️ 请注意,字体文件名可能与实际字体名称不同!为了获取正确的完整字体名称,请将字体文件上传到 fontgauntlet.com

原生工具

// First, you have to get information about the variable font (axes names, IDs, and allowed values). But the current axis value isn't there 🤷‍♂️
// Here you can face a problem, like the custom font wasn't added to the project, was added incorrectly, or font name isn't correct
let uiFont = UIFont(name: "Martian Mono", size: 16.0)!
let ctFont = CTFontCreateWithName(uiFont.fontName as CFString, 16.0, nil)
let variationAxes = CTFontCopyVariationAxes(ctFont) as! [Any] // font information with weird format 👎

// To set new values you need to know the correct axis IDs and allowed values (maxValue and minValue)
let variations = [2003265652: 600, 2003072104: 100] // 2003265652 - 'Weight'; 2003072104 - `Width`

// As we know, text elements in UIKit use the UIFont class. So, you have to create new UIFont object with new values for axes
let uiFontDescriptor = UIFontDescriptor(fontAttributes: [.name: uiFont.fontName, kCTFontVariationAttribute as UIFontDescriptor.AttributeName: variations])
let newUIFont = UIFont(descriptor: uiFontDescriptor, size: uiFont.pointSize) 
// Now, you can apply the UIFont object for UI text elements
// Here you may notice the name of the new UIFont object has been changed to 'MartianMono-Regular_wght2580000_wdth640000'
let label = UILabel()
label.font = newUIFont

如果您想继续更改当前的字体对象,或者您想创建更复杂的逻辑,您需要存储 UIFont 对象。此外,您还应该解析变体轴值并存储它们。但不用担心,VFont 会为您完成这一切!

VFont 库

UIKit

import VFont

let vFont = VFont(name: "Martian Mono", size: 16)! // UIFont like initialization
vFont.setValue(400, forAxisID: 2003265652) // setting a new value for the 'Weight' axis

let label = UILabel()
label.font = vFont.uiFont // apply the variable font for a UI text element
vFont.getAxesDescription() // get the font information with а human readable format, if you need it ✅

// override the `updated` closure to observe all font changes, if you're going to change it at runtime
vFont.updated = { uiFont in
    label.font = uiFont
}

SwiftUI

struct ContentView: View {

    var body: some View {
       Text("Title 1")
          .font(.vFont("Martian Mono", size: 16, axisID: 2003265652, value: 450))
       Text("Title 2")
           .font(.vFont("Inter", size: 32, axes: [2003072104: 80, 2003265652: 490])
    }
    
}

为什么我们使用数字 ID 而不是轴名称?好问题!但答案很简单。在底层处理可变字体的 CTFont 框架会为不同的系统语言返回不同的轴名称。这意味着只有轴数字 ID 是唯一值。如果您找到一种无论系统语言如何都能接收到英文名称的方法,我将非常感激!

安装

Swift Package Manager

Cocoapods

要使用 CocoaPods 将 VFont 集成到您的 Xcode 项目中,请在您的 Podfile 中指定它。

pod 'VFont'

高级用法

如果您使用 UIKit,您可以创建自己的字体类,继承 VFont 类!

UIKit

import VFont

final class MartianMono: VFont {
    
    init?(size: CGFloat) {
        super.init(name: "Martian Mono", size: size)
    }
    
    var weight: CGFloat {
        get {
            return axes[2003265652]?.value ?? .zero
        } set {
            setValue(newValue, axisID: 2003265652)
        }
    }
    
    var width: CGFloat {
        get {
            return axes[2003072104]?.value ?? .zero
        } set {
            setValue(newValue, axisID: 2003072104)
        }
    }
    
}
let font = MartianMono(size: 16)
        
font?.weight = 300
font?.width = 90

SwiftUI

SwiftUI 项目中,您可以创建一个 static method 作为 Font 结构体的扩展。

extension Font {
    
    static func martianMono(size: CGFloat, width: CGFloat = 0, weight: CGFloat = 0) -> Font {
        return .vFont("Martian Mono", size: size, axes: [
            2003072104: width,
            2003265652: weight
        ])
    }
    
}
struct ContentView: View {
    
    var body: some View {
        Text("Hello, world!")
            .font(.martianMono(size: 16, width: 300, weight: 100))
    }
    
}

示例

转到 Examples 并研究它是如何工作的!此外,您可以在 Xcode 中启动这些示例。为此,请克隆存储库并启动 VFont.xcworkspace 文件。

vfont-uikit-demo.mp4

路线图

许可证

VFont 在 MIT 许可证下发布。查看 LICENSE 了解详情。