📚

ZStackとbackground(overlay)修飾子の使い分けできてる?

2024/10/15に公開

この記事では、SwiftUIでUIを実装する時の ZStackbackground(overlay)修飾子 の使い分けについて整理していきます。

Componentを重ねてデザインを実装する

下記のようなUIをSwiftUIで実装する時に、どう実装しますか?

パッと思いつく方法だと下記の2つがありそうです。

ZStackを使う
ZStack {
    Circle()
        .fill(Color.CustomGreen)
        .frame(width: 200, height: 200)

    Text("Sample1")
        .foregroundStyle(Color.white)
        .font(.regular15)
}
background修飾子を使う
Text("Sample1")
    .foregroundStyle(Color.white)
    .font(regular15)
    .background(
        Circle()
            .fill(Color.CustomGreen)
            .frame(width: 200, height: 200)
    )

ビルドして表示してみると、どちらも同じ結果になり期待通りのUIを実装できています。
では、画面上に他のComponentがある場合はどうでしょうか?

画面上に他のComponentがある場合

例として、上記のUIの下に Text を配置してみます。

ZStackを使う
VStack(spacing: 24) {
    ZStack {
        Circle()
            .fill(Color.CustomGreen)
            .frame(width: 200, height: 200)
    
        Text("Sample1")
            .foregroundStyle(Color.white)
            .font(.regular15)
    }

    // Textを追加
    Text("Sample2")
        .foregroundStyle(Color.white)
        .font(.regular15)
}
background修飾子を使う
VStack(spacing: 24) {
    Text("Sample1")
        .foregroundStyle(Color.white)
        .font(regular15)
        .background(
            Circle()
                .fill(Color.CustomGreen)
                .frame(width: 200, height: 200)
        )

    // Textを追加
    Text("Sample2")
        .foregroundStyle(Color.white)
        .font(.regular15)
}

上記の実行結果はどうなるでしょうか?続きを読む前に予想してみてください。

クリックして、実行結果を確認
ZStackを使う background修飾子を使う

実行結果が予想通りで、なぜそうなるのか説明できる方はこの先を読む必要はないです🙇‍♂️

ZStackとbackground(overlay)修飾子の違い

実行結果になぜこのような違いがあるかというと、実際のレイアウトを確認すると分かりやすいです。

クリックして、レイアウトを確認
ZStackを使う background修飾子を使う

レイアウトからも分かる通り、VStack のspacingや padding修飾子 を使うSwiftUIでのmargin設定では、background(overlay)修飾子で追加した要素は考慮されません。

「background(overlay)修飾子はあくまで修飾子なので、今回の例で言うとbackground修飾子で追加した Circle はレイアウトを構成する要素としてカウントされていません。(テキストカラー等と同じ扱い)」

そのため今回の例では、

  • ZStackを使った場合
    • 「ZStackで実装した、円の中にテキストがあるView」 と「Sample2を表示しているText」との間に VStack のspacingが設定されます。
  • background修飾子を使った場合
    • 「Sample1を表示しているText」 と「Sample2を表示しているText」との間に VStack のspacingが設定されます。

このように整理すると、background(overlay)修飾子を使う機会がないように感じますが、下記のような場合はbackground(overlay)修飾子が有効です。

具体例を挙げると、テキストに背景色を追加する場合は下記のようにスッキリ書けます。
このように書くと、表示する文字列に合わせて Text のサイズが変わりますが、その Text サイズに合わせて背景色を指定できます。

background修飾子を使う
Text("Sample1")
    .foregroundStyle(Color.white)
    .font(regular15)
    .frame(width: 200, height: 200)
    .background(
        Color.CustomGreen
    )

background(overlay)修飾子を使うときの注意点は

サイズを指定する場合
Text("Sample1")
    .foregroundStyle(Color.white)
    .font(regular15)
    .frame(width: 200, height: 200) // 先にView側でサイズを指定する
    .background(
        Color.CustomGreen
    )

最後に

この記事を書くにあたって、サンプルのコードを色々検討しつつ実装していて、SwiftUIは深く理解しなくてもほとんどのUIが実装できますが、 それぞれの特性をちゃんと理解して正しく実装することが大事 だなと実感しました。

株式会社Kyash

Discussion