[SwiftUI] Text の LineHeight をデザインに合わせたら余分なスペースができて困った話

8847 ワード

デザインの Text 表示について

普段アプリデザインを相談する際に Figma を利用しているが、
Figma で Text を書くと LineHeight が加わっていることが多い。

上の例は1行の Text が2つ縦に並んでいる。
Text のサイズは 16px、LineHeight が 24px になっている。
そのため Text のサイズに加えて、8px 分の余白が上下に入っていることが分かる。

もちろん Figma で LineHeight を Text のサイズと合わせることもできるが、
今回はデザインオーダーとして LineHeight を考慮した Text の実装を行う。

SwiftUI の Text に LineHeight を追加する

1行の Text に LineHeight を追加する方法はこちらを参考にした。
独自の ViewModifier を実装し Text に適用することで実現できるとのこと。

参考記事を元に書いた
struct ContentView: View {
  VStack {
    Text("もじ文字モジ")
      .modifier(TextModifier()) // Text サイズと LineHeight を適用
    Text("もじ文字モジ")
      .modifier(TextModifier())
  }
}

struct TextModifier: ViewModifier {
  func body(content: Content) -> some View {
    content
      .font(.system(size: 16))
      .lineSpacing(lineHeight - font.lineHeight)
      .padding(.vertical, (lineHeight - font.lineHeight) / 2)
  }
}

lineHeight - font.lineHeight の部分は、LineHeight と Text の高さ(サイズ)との差になるため、上の例で言うと 24px - 16px = 8px となる。

Modifier適用前後の比較は以下の通り。

Modifier適用前 Modifier適用後

とりあえず LineHeight は加わっていそう。

困ったこと

LineHeight が加わったので安心していたのだが、デザインと見比べてみると...

デザイン Modifier適用後

余白が多い!🤔

デザイン通りに LineHeight を適用したはずが、全然違う結果になってしまった。

原因

Xcode で Preview を見てみると、

Text と Text の間にスペースができている!
SwiftUIでは View の余白は Margin ではなく全て Padding で行うため、どうやら Text の Padding ではなさそう...

解決方法

色々調べてみるとこちらの方法で解決することがわかった。

参考記事を元に書いた
struct ContentView: View {
  VStack(spacing: 0) { // <--- ここを変更
    Text("もじ文字モジ")
      .modifier(TextModifier()) // Text サイズと LineHeight を適用
    Text("もじ文字モジ")
      .modifier(TextModifier())
  }
}

struct TextModifier: ViewModifier {
  // ~~~ 略 ~~~
}

今度はどうやら VStack に原因があるようで、 spacing: 0 を書かないと今回のように View 間でスペースができてしまうらしい...

スペースが邪魔なので、VStackを修正してみる。

デザイン VStack修正後

デザインの LineHeight と一致しているように見える!(わかりにくい)

ということで、Text に LineHeight を適用するときは注意したほうが良さそうという話でした。
あと毎回 VStack に spacing: 0 をつけるのは面倒なので、何か良い方法があれば教えてください...