修复 SwiftUI 中自定义字体的行间距
Fix line spacing in custom font in SwiftUI
我正在使用自定义字体 (Catamaran),它的行与行之间似乎有很大的 space。例如我有这个代码:
Text("Example text that has big space between lines")
.lineSpacing(0)
.padding(.horizontal)
.font(Font.custom(FontNameManager.Catamaran.bold, size: 24.0))
.foregroundColor(.white)
.multilineTextAlignment(.center)
看起来像这样:
如您所见,行与行之间没有零 space,但它仍然变得太多 space。我什至尝试将负数设置为 lineSpacing 方法,但它没有帮助。我能用这个做什么?我该如何解决?在 UIKit 中,我可能会使用属性字符串,我想我可以将 UILabel 用作 UIViewRepresentable,然后我可以在 SwiftUI 中使用属性字符串 iOS 14. 是否有一些更简单的解决方案可以“修复”字体以供任何使用?我必须编辑原始 .ttf 文件吗?为什么这个字体的行与行之间有这个space?
感谢您的帮助
SwiftUI 可能会使用 hhea
(水平 header table)的值来设置 Text
框高度。在您的例子中,双体船的上升高度为 1100,下降高度为 540。箱体高度将计算为这两个值的总和:540 + 1100 = 1640。而字体的UPM(Units per Em)默认为1000。这意味着在 SwiftUI 中,当设置 .font(.custom(..., size: 1000))
时, Text()
的每一行都会有一个框架,其高度为 1640.
在.lineSpacing()
方面,SwiftUI 没有设置基线之间的间距值,而是设置两个框之间的间距。如果您希望在下面的示例中两个框之间没有间距,不幸的是将 .lineSpacing()
设置为 -(1640-1000) = -640
是不允许的(负值不接受 table)。
更新:一个UIViewRepresentable
方法
但是,您可以使用 UILabel
来减少行高:
struct CustomText: UIViewRepresentable {
let text: String
let font: UIFont
func makeUIView(context: Context) -> UILabel {
let label = UILabel()
label.font = font
label.numberOfLines = 0
let attributedString = NSMutableAttributedString(string: text)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineHeightMultiple = 0.6 // <- Reduce lineHeight with a <1 factor
attributedString.addAttribute(NSAttributedString.Key.paragraphStyle,
value: paragraphStyle,
range: NSMakeRange(0, attributedString.length))
label.attributedText = attributedString
return label
}
func updateUIView(_ uiView: UILabel, context: Context) { }
}
用法:
CustomText(text: "Foggy Days\nGo Nowhere",
font: UIFont(name: "Catamaran", size: 1000)!)
.leading 似乎是您需要的东西(并且在印刷上是谈论 'line spacing' 的正确方式)。
使用:
Font.system(size: 16, weight: .regular, design: .rounded)
.leading(.tight)
我正在使用自定义字体 (Catamaran),它的行与行之间似乎有很大的 space。例如我有这个代码:
Text("Example text that has big space between lines")
.lineSpacing(0)
.padding(.horizontal)
.font(Font.custom(FontNameManager.Catamaran.bold, size: 24.0))
.foregroundColor(.white)
.multilineTextAlignment(.center)
看起来像这样:
如您所见,行与行之间没有零 space,但它仍然变得太多 space。我什至尝试将负数设置为 lineSpacing 方法,但它没有帮助。我能用这个做什么?我该如何解决?在 UIKit 中,我可能会使用属性字符串,我想我可以将 UILabel 用作 UIViewRepresentable,然后我可以在 SwiftUI 中使用属性字符串 iOS 14. 是否有一些更简单的解决方案可以“修复”字体以供任何使用?我必须编辑原始 .ttf 文件吗?为什么这个字体的行与行之间有这个space?
感谢您的帮助
SwiftUI 可能会使用 hhea
(水平 header table)的值来设置 Text
框高度。在您的例子中,双体船的上升高度为 1100,下降高度为 540。箱体高度将计算为这两个值的总和:540 + 1100 = 1640。而字体的UPM(Units per Em)默认为1000。这意味着在 SwiftUI 中,当设置 .font(.custom(..., size: 1000))
时, Text()
的每一行都会有一个框架,其高度为 1640.
在.lineSpacing()
方面,SwiftUI 没有设置基线之间的间距值,而是设置两个框之间的间距。如果您希望在下面的示例中两个框之间没有间距,不幸的是将 .lineSpacing()
设置为 -(1640-1000) = -640
是不允许的(负值不接受 table)。
更新:一个UIViewRepresentable
方法
但是,您可以使用 UILabel
来减少行高:
struct CustomText: UIViewRepresentable {
let text: String
let font: UIFont
func makeUIView(context: Context) -> UILabel {
let label = UILabel()
label.font = font
label.numberOfLines = 0
let attributedString = NSMutableAttributedString(string: text)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineHeightMultiple = 0.6 // <- Reduce lineHeight with a <1 factor
attributedString.addAttribute(NSAttributedString.Key.paragraphStyle,
value: paragraphStyle,
range: NSMakeRange(0, attributedString.length))
label.attributedText = attributedString
return label
}
func updateUIView(_ uiView: UILabel, context: Context) { }
}
用法:
CustomText(text: "Foggy Days\nGo Nowhere",
font: UIFont(name: "Catamaran", size: 1000)!)
.leading 似乎是您需要的东西(并且在印刷上是谈论 'line spacing' 的正确方式)。
使用:
Font.system(size: 16, weight: .regular, design: .rounded)
.leading(.tight)