跳到主要内容

SwiftUI 自定义字体实现自适应大小(Dynamic Type)

· 阅读需 4 分钟
GoSwiftUI
goswiftui.com

Dynamic Type是 Apple 预定义的传达语义含义的文本样式。

Dynamic Type 的好处是它会根据当前的可访问性设置自动放大和缩小文本大小

从 iOS 14开始,如果您使用Font.custom(_:size:)创建自定义字体,您的字体将根据正文文本样式自动缩放。

下面是使用创建的自定义字体的示例Font.custom(_:size:)

HStack {
VStack {
Text("Large Title")
.font(.largeTitle)
Text("Title 1")
.font(.title)
Text("Title 2")
.font(.title2)
Text("Title 3")
.font(.title3)
Text("Body")
.font(.body)
Text("Callout")
.font(.callout)
Text("Footnote")
.font(.footnote)
Text("Caption 1")
.font(.caption)
Text("Caption 2")
.font(.caption2)
}
VStack {
Text("Large Title")
.font(
.custom(
"Silkscreen-Regular",
size: 34
)
)
Text("Title 1")
.font(
.custom(
"Silkscreen-Regular",
size: 28
)
)
Text("Title 2")
.font(
.custom(
"Silkscreen-Regular",
size: 22
)
)
Text("Title 3")
.font(
.custom(
"Silkscreen-Regular",
size: 20
)
)
Text("Body")
.font(
.custom(
"Silkscreen-Regular",
size: 17
)
)
Text("Callout")
.font(
.custom(
"Silkscreen-Regular",
size: 16
)
)
Text("Footnote")
.font(
.custom(
"Silkscreen-Regular",
size: 13
)
)
Text("Caption 1")
.font(
.custom(
"Silkscreen-Regular",
size: 12
)
)
Text("Caption 2")
.font(
.custom(
"Silkscreen-Regular",
size: 11
)
)
}
}

正如你所看到的,字体可以向上和向下扩展,但这有一些奇怪的地方。

我们的自定义字体在大的可访问性设置上似乎有点偏差。

使用正文文本样式自动缩放的自定义字体。

这个问题的原因是,每个文本样式都有不同的缩放系数

使用Font.custom(_:size:)意味着你用主体文本样式的缩放系数来缩放它。

为了解决这个问题,你必须为每个文本应用不同的文本样式。

如何在 SwiftUI 自定义字体时使用 Dynamic Type

为了正确地缩放一个自定义字体,你应该明确你要相对于哪个文本样式进行缩放。

您可以使用Font.custom(_:size:relativeTo:)指定。

这个方法的变化接受一个额外的参数 relativeTo,它接受一个你想要缩放的 TextStyle

下面是一个例子,说明我们如何使用与 largeTitle 文本样式相同的比例系数来缩放字体。

Text("Large Title")
.font(.custom("Silkscreen-Regular", size: 34, relativeTo: .largeTitle))

让我们尝试使用这种新方法,看看有什么不同。这是我们的新字体集。

VStack {
Text("Large Title")
.font(
.custom(
"Silkscreen-Regular",
size: 34,
relativeTo: .largeTitle
)
)
Text("Title 1")
.font(
.custom(
"Silkscreen-Regular",
size: 28,
relativeTo: .title
)
)
Text("Title 2")
.font(
.custom(
"Silkscreen-Regular",
size: 22,
relativeTo: .title2
)
)
Text("Title 3")
.font(
.custom(
"Silkscreen-Regular",
size: 20,
relativeTo: .title3
)
)
Text("Body")
.font(
.custom(
"Silkscreen-Regular",
size: 17,
relativeTo: .body
)
)
Text("Callout")
.font(
.custom(
"Silkscreen-Regular",
size: 16,
relativeTo: .callout
)
)
Text("Footnote")
.font(
.custom(
"Silkscreen-Regular",
size: 13,
relativeTo: .footnote
)
)
Text("Caption 1")
.font(
.custom(
"Silkscreen-Regular",
size: 12,
relativeTo: .caption
)
)
Text("Caption 2")
.font(
.custom(
"Silkscreen-Regular",
size: 11,
relativeTo: .caption2
)
)
}

正如你所看到的,我们的自定义字体现在与系统字体比例更好地保持一致。

Font.custom(_:size:relativeTo:)