如何在 SwiftUI 中缩放系统字体以支持动态类型?
How to scale system font in SwiftUI to support Dynamic Type?
在 UIKit 中,我可以像这样更改 UILabel 的字体大小以支持使用系统字体的动态类型:
UIFontMetrics.default.scaledFont(for: UIFont.systemFont(ofSize: 16))
我是不是弄错了,或者在 SwiftUI 中没有办法做这样的事情?
既要使用系统字体又要支持Dynamic Type,是否可以只使用默认字体样式.title等?
来自 HackingWithSwift 的 This solution 似乎只适用于自定义字体,对吧?
提前感谢您的任何建议!
以下方法有效(使用 Xcode 11.2.1 / iOS 13.2.2 测试)
var body: some View {
Text("Hello, World!") // direct text .font
.font(Font.system(size: UIFontMetrics.default.scaledValue(for: 16)))
}
以及基于视图的修饰符
VStack {
Text("Hello, World!")
}
.font(Font.system(size: UIFontMetrics.default.scaledValue(for: 16)))
您可以创建一个 ViewModifier
和一个 View
扩展,就像您提到的 HackingWithSwift 文章中那样,但它使用系统字体。
struct ScaledFont: ViewModifier {
// From the article:
// Asks the system to provide the current size category from the
// environment, which determines what level Dynamic Type is set to.
// The trick is that we don’t actually use it – we don’t care what the
// Dynamic Type setting is, but by asking the system to update us when
// it changes our UIFontMetrics code will be run at the same time,
// causing our font to scale correctly.
@Environment(\.sizeCategory) var sizeCategory
var size: CGFloat
func body(content: Content) -> some View {
let scaledSize = UIFontMetrics.default.scaledValue(for: size)
return content.font(.system(size: scaledSize))
}
}
extension View {
func scaledFont(size: CGFloat) -> some View {
return self.modifier(ScaledFont(size: size))
}
}
用法示例:
var body: some View {
Text("Hello, World!").scaledFont(size: 18)
}
您可以使用 Xcode 12 上的“环境覆盖”面板对其进行测试。
只要你有
@Environment(\.sizeCategory) var sizeCategory
加载文件层次结构中的某处,.font(Font.system(size: UIFontMetrics.default.scaledValue(for: 16)))
会随着系统字体大小的变化而变化。
上面发布的视图修饰符@Mokkun 有效,因为它包含环境变量 sizeCategory
。
将环境变量 sizeCategory
放在任何 SwiftUI 视图的顶部,然后直接使用 UIFontMetrics.default.scaledValue(...)
也可以。像这样:
import SwiftUI
struct ContentViewSheet: View {
@Environment(\.sizeCategory) var sizeCategory
var body: some View {
Text("Hello world")
.font(Font.system(size: UIFontMetrics.default.scaledValue(for: 16)))
}
}
在 UIKit 中,我可以像这样更改 UILabel 的字体大小以支持使用系统字体的动态类型:
UIFontMetrics.default.scaledFont(for: UIFont.systemFont(ofSize: 16))
我是不是弄错了,或者在 SwiftUI 中没有办法做这样的事情? 既要使用系统字体又要支持Dynamic Type,是否可以只使用默认字体样式.title等?
来自 HackingWithSwift 的This solution 似乎只适用于自定义字体,对吧?
提前感谢您的任何建议!
以下方法有效(使用 Xcode 11.2.1 / iOS 13.2.2 测试)
var body: some View {
Text("Hello, World!") // direct text .font
.font(Font.system(size: UIFontMetrics.default.scaledValue(for: 16)))
}
以及基于视图的修饰符
VStack {
Text("Hello, World!")
}
.font(Font.system(size: UIFontMetrics.default.scaledValue(for: 16)))
您可以创建一个 ViewModifier
和一个 View
扩展,就像您提到的 HackingWithSwift 文章中那样,但它使用系统字体。
struct ScaledFont: ViewModifier {
// From the article:
// Asks the system to provide the current size category from the
// environment, which determines what level Dynamic Type is set to.
// The trick is that we don’t actually use it – we don’t care what the
// Dynamic Type setting is, but by asking the system to update us when
// it changes our UIFontMetrics code will be run at the same time,
// causing our font to scale correctly.
@Environment(\.sizeCategory) var sizeCategory
var size: CGFloat
func body(content: Content) -> some View {
let scaledSize = UIFontMetrics.default.scaledValue(for: size)
return content.font(.system(size: scaledSize))
}
}
extension View {
func scaledFont(size: CGFloat) -> some View {
return self.modifier(ScaledFont(size: size))
}
}
用法示例:
var body: some View {
Text("Hello, World!").scaledFont(size: 18)
}
您可以使用 Xcode 12 上的“环境覆盖”面板对其进行测试。
只要你有
@Environment(\.sizeCategory) var sizeCategory
加载文件层次结构中的某处,.font(Font.system(size: UIFontMetrics.default.scaledValue(for: 16)))
会随着系统字体大小的变化而变化。
上面发布的视图修饰符@Mokkun 有效,因为它包含环境变量 sizeCategory
。
将环境变量 sizeCategory
放在任何 SwiftUI 视图的顶部,然后直接使用 UIFontMetrics.default.scaledValue(...)
也可以。像这样:
import SwiftUI
struct ContentViewSheet: View {
@Environment(\.sizeCategory) var sizeCategory
var body: some View {
Text("Hello world")
.font(Font.system(size: UIFontMetrics.default.scaledValue(for: 16)))
}
}