简体   繁体   English

修复 SwiftUI 中自定义字体的行距

[英]Fix line spacing in custom font in SwiftUI

I am using custom font ( Catamaran ) and it seems like it has big space between lines in it.我正在使用自定义字体( Catamaran ),它的行之间似乎有很大的空间。 For example I have this code:例如我有这个代码:

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)

and it looks like this:它看起来像这样:

带有来自先前代码的文本示例的屏幕截图

As you can see it doesn't have zero space between lines but it still gets too much space.正如你所看到的,它的行之间没有零空间,但它仍然有太多的空间。 I even tried to set negative numbers to lineSpacing method but it doesn't help.我什至尝试将负数设置为 lineSpacing 方法,但它没有帮助。 What can I do with this?我能用这个做什么? How I can fix it?我该如何解决? In UIKit I would probably use attributed string and I think I can use UILabel as UIViewRepresentable and then I can use attributed string in SwiftUI iOS 14. Is there some easier solution which can "fix" font for any usage?在 UIKit 中,我可能会使用属性字符串,我想我可以使用 UILabel 作为 UIViewRepresentable,然后我可以在 SwiftUI iOS 14 中使用属性字符串。是否有一些更简单的解决方案可以“修复”任何使用的字体? Do I have to edit original .ttf file?我必须编辑原始 .ttf 文件吗? Why there is this space between lines in this font?为什么这种字体的行之间有这个空格?

Thanks for any help谢谢你的帮助

SwiftUI might use values of hhea (Horizontal header table) to set the Text box height. SwiftUI 可能会使用hhea (水平标题表)的值来设置Text框高度。 In your case, Catamaran has an ascender of 1100 and a descender of 540. The box height will be calculated as the sum of these two values: 540 + 1100 = 1640 .在您的情况下,双体船的上升部为 1100,下降部为 540。框高度将计算为这两个值的总和: 540 + 1100 = 1640 And the UPM (Units per Em) of the font is default 1000 .字体的 UPM(Units per Em)默认为1000 Which means in SwiftUI, when .font(.custom(..., size: 1000)) is set, each line of Text() will have a frame whose height is 1640 .这意味着在 SwiftUI 中,当.font(.custom(..., size: 1000))被设置时, Text()每一行都会有一个高度为1640的框架。

文本框高度

In terms of .lineSpacing() , SwiftUI doesn't set the value for spacing between baselines, but spacing between two boxes instead..lineSpacing() ,SwiftUI 不会设置基线之间的间距值,而是设置两个框之间的间距值。 If you want to have no spacing between two boxes in the example below, unfortunately setting .lineSpacing() to -(1640-1000) = -640 is not allowed (negative values not acceptable).如果你想在下面的例子中没有两个框之间的间距,不幸的是,将.lineSpacing()设置为-(1640-1000) = -640是不允许的(负值是不可接受的)。

设置与预期行距

UPDATE: An UIViewRepresentable Method更新:一个UIViewRepresentable方法

However, you can use UILabel instead to reduce line height:但是,您可以改用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) { }
}

Usage:用法:

CustomText(text: "Foggy Days\nGo Nowhere",
           font: UIFont(name: "Catamaran", size: 1000)!)

.leading seems like a thing you need (and is typographically the correct way to talk about 'line spacing'). .leading似乎是您需要的东西(并且在印刷上是谈论“行距”的正确方式)。

Use:利用:

Font.system(size: 16, weight: .regular, design: .rounded)
.leading(.tight)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM