如何在 SwiftUI 中设置单行文本的行高?

How to set line height for a single line text in SwiftUI?

目前,我一直在使用.lineSpacing(...),但这只适用于多行文本

/// Sets the amount of space between lines of text in this view.
///
/// - Parameter lineSpacing: The amount of space between the bottom of one
///   line and the top of the next line.
@inlinable public func lineSpacing(_ lineSpacing: CGFloat) -> some View

这意味着我很难准确翻译 sketch/figma 中的字体,我需要尝试调整填充以使其正确。这是一个显示此内容的示例:

VStack {
    // Line spacing is ignored.
    Text("Hello, World!")
        .background(Color.green)
        .lineSpacing(50)

    Spacer()

    // Line spacing is correct.
    Text("Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts and visual mockups.")
        .background(Color.green)
        .lineSpacing(50)
}

您可以只使用 .frame 修饰符并设置高度。

Xcode 12

使用 .leading() 修饰符调整行距。

Text("Hello\nworld").font(Font.body.leading(.tight))

当前支持的值:.tight.standard.loose

来源:Apple Documentation

为了让您的文字与 figma 相匹配,这就是最终对我有用的方法。例如,如果您的 figma 设计具有 16 pt 的特定字体和 32 pt 的行高:

let font = UIFont(name: "SomeFont", size: 16)!
return Text("Some Text")
    .font(.custom("SomeFont", size: 16))
    .lineSpacing(32 - font.lineHeight)
    .padding(.vertical, (32 - font.lineHeight) / 2)

为了获得准确的行距值,我们必须用字体固有的行高减去我们想要的行高,但正如您所指出的,这只会对多行文本和行间生效。我们仍然需要考虑文本的顶部和底部填充以匹配所需的行高,因此再次添加总行高减去字体的行高。

我已成功使用以下组合:

  • .frame(minHeight: lineHeight)
  • .lineSpacing(abs(designSystemFont.lineHeight - uiKitFont.lineHeight))

The abs may not be needed (assuming the system's line height is taller than the default one, but you never know if that may change, so...)

这使我能够在尊重设计系统要求的同时处理 single-line 文本。

根据 Dan Hassan 的回答,我为自己制作了一个 ViewModifier 来执行此操作,看起来它按预期工作

import SwiftUI

struct FontWithLineHeight: ViewModifier {
    let font: UIFont
    let lineHeight: CGFloat

    func body(content: Content) -> some View {
        content
            .font(Font(font))
            .lineSpacing(lineHeight - font.lineHeight)
            .padding(.vertical, (lineHeight - font.lineHeight) / 2)
    }
}

extension View {
    func fontWithLineHeight(font: UIFont, lineHeight: CGFloat) -> some View {
        ModifiedContent(content: self, modifier: FontWithLineHeight(font: font, lineHeight: lineHeight))
    }
}

实际上对我有用的是(基于 Ole-Kristian 的回答)

import SwiftUI

struct FontWithLineHeight: ViewModifier {
    let font: UIFont
    let lineHeight: CGFloat

    func body(content: Content) -> some View {
        content
            .font(Font(font))
            .lineSpacing((token.lineHeight - token.font.lineHeight)/2)
            .padding(.vertical, (token.lineHeight - token.font.lineHeight))
    }
}

extension View {
    func fontWithLineHeight(font: UIFont, lineHeight: CGFloat) -> some View {
        ModifiedContent(content: self, modifier: FontWithLineHeight(font: font, lineHeight: lineHeight))
    }
}

...与填充值和 lineSpacing 值相反的其他答案非常相似。

这是我让底部 'padding' 与 Figma 相同的唯一方法。