【问题标题】:How to set line height for a single line text in SwiftUI?如何在 SwiftUI 中为单行文本设置行高?
【发布时间】:2020-08-25 13:07:26
【问题描述】:

目前,我一直在使用.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

这意味着我更难从草图/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)
}

【问题讨论】:

  • 我没有明白你的意思,但是,如果它适合你,试试这个:在一行的末尾添加“\n”Text
  • 您对第一个文本有何期望?字体如何与主题相关 - 两个文本块中的字体相同?
  • @EnesKaraosman 我不想添加新行,我想增加单行的空间。
  • 我无法说服自己,单行应该如何有间距。 lineSpacing 方法名很清楚,你也访问过 SwiftUI 的界面看解释,也有说“设置之间的空间量...”:(
  • SwiftUI 文本不提供 lineHeight 属性(行间距是另一种野兽)。您可以尝试对齐“firstTextBaseLine”以获得所需的行为。或者,使用带有属性字符串的“UILabel”(通过“UIViewRepresentable”)(在段落样式中指定行高)。

标签: ios swift iphone xcode swiftui


【解决方案1】:

根据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))
    }
}

【讨论】:

  • 更新它以使用Font 可能更好?还是无法从 SwiftUI 字体访问lineHeight
  • 正确,Font 没有 lineHeight,所以我必须通过 UIFont。
  • 我只是懒惰的 UIFont 初始化器;如果我有时间,将在一次调用中发布包含尺寸、重量和行距的更新。
  • 有人想出解决负面.lineSpacing 的方法吗?好像如果你传入一个负数,它就会被视为 0。
  • 视图扩展方法可以简化为modifier(FontWithLineHeight(font: font, lineHeight: lineHeight))
【解决方案2】:

为了让你的文字与 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)

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

【讨论】:

  • 很好,把它放在视图修饰符中会很棒;)
【解决方案3】:

Xcode 12

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

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

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

来源:Apple Documentation

【讨论】:

  • 这不能回答我的问题,但你可以这样做还是很酷的!也许坚持这三个选项中的任何一个都比从设计师那里获得实际价值要好,但有时,设计就是设计,因此不能默认为应用程序标准。
【解决方案4】:

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

【讨论】:

  • 我宁愿避免硬编码的帧大小,因为这不会随着字体、布局或内容的变化而自动调整。
【解决方案5】:

我已经成功使用了以下组合:

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

abs 可能不需要(假设系统的行高高于默认值,但你永远不知道这是否会改变,所以...)

这允许我在处理单行文本的同时尊重设计系统要求。

【讨论】:

    【解决方案6】:

    实际上对我有用的是(基于 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 的值颠倒了。

    这是使底部“填充”与 Figma 相同的唯一方法。

    【讨论】:

      猜你喜欢
      • 2015-07-01
      • 1970-01-01
      • 2010-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-04
      相关资源
      最近更新 更多