MathPython491378 views
ヒストリア284143 views
小学社会308636 views
中学理科1626207 views
英語607877 views
高校物理158224 views
中学英語808712 views
中学社会667106 views
高校国語785655 views
高校化学2913383 views
Help
Tools

English

SwiftUI モディファイアの適用順序

SwiftUI のモディファイアは、適用する順序によって結果が大きく変わる。これは SwiftUI の根本的な仕組みに関わる重要な概念で、理解しないと意図しないレイアウトに悩まされることになる。

モディファイアは「ラップ」する

SwiftUI のモディファイアは、元のビューを新しいビューで包み込む。チェーンの各ステップで新しいビューが生成される。

Text("Hello")
    .padding()
    .background(.blue)

このコードは、Text を Padding でラップし、さらにそれを Background でラップしている。結果として、青い背景はパディングを含む領域に適用される。

Text("Hello")
    .background(.blue)
    .padding()

順序を入れ替えると、青い背景は Text のみに適用され、パディングは背景の外側に追加される。

視覚的な違いを確認

// パターン A: padding → background
Text("A")
    .padding(20)
    .background(.red)

// パターン B: background → padding
Text("B")
    .background(.red)
    .padding(20)
パターン A

テキストの周りにパディングがあり、その全体が赤い背景で覆われる。背景は大きい。

パターン B

テキストだけが赤い背景で覆われ、その外側にパディングがある。背景は小さい。

frame の順序

frame も同様に順序が重要だ。

Text("Hello")
    .frame(width: 200, height: 100)
    .background(.green)
    .frame(width: 300, height: 150)
    .background(.orange)

最初の frame で 200×100 の領域が確保され、緑の背景がそこに適用される。次の frame で 300×150 に拡大され、オレンジの背景は拡大後の領域に適用される。緑の矩形がオレンジの矩形の中央に配置された、入れ子構造になる。

クリッピングと角丸

cornerRadius(または clipShape)と frame の順序も影響を受ける。

// 角丸が内側に
Image("photo")
    .resizable()
    .frame(width: 100, height: 100)
    .clipShape(RoundedRectangle(cornerRadius: 20))

// 角丸が外側に
Image("photo")
    .resizable()
    .clipShape(RoundedRectangle(cornerRadius: 20))
    .frame(width: 100, height: 100)

最初の例では、100×100 にリサイズしてから角丸でクリップする。2 番目は先にクリップしてからリサイズするため、角丸の比率が変わる可能性がある。

影の順序

shadow も順序の影響を受ける典型例だ。

Text("Shadow")
    .padding()
    .background(.white)
    .shadow(radius: 5)  // 背景全体に影

Text("Shadow")
    .padding()
    .shadow(radius: 5)  // テキストだけに影
    .background(.white)

shadow はそれより上のモディファイアで構成されたビュー全体に適用される。background を shadow の後に置くと、背景には影がつかない。

複数の同じモディファイア

同じモディファイアを複数回使うこともできる。

Text("Nested")
    .padding(10)
    .background(.red)
    .padding(10)
    .background(.blue)
    .padding(10)
    .background(.green)

赤→青→緑と入れ子になった背景が作られる。これを利用して、ボーダー風の効果を作ることもできる。

overlay と background

overlay と background も順序に注意が必要だ。

Rectangle()
    .fill(.blue)
    .frame(width: 100, height: 100)
    .overlay(
        Circle().fill(.red).frame(width: 50, height: 50)
    )
    .padding()

overlay は「その時点でのビュー」の上に重ねる。padding を overlay の後に置くと、赤い円は青い四角形の中央に配置されたまま、全体にパディングが追加される。

実用的なガイドライン

レイアウト系は内側から

frame、padding などは、コンテンツに近い位置から適用していくのが基本。

装飾系は対象の直後

background、border、shadow は、装飾したいビューの直後に置く。

クリッピングは最後

clipShape は、最終的なサイズが決まった後に適用するのが一般的。

モディファイアの順序を意識することで、予測可能なレイアウトが実現できる。迷ったときは、各ステップで background(.red.opacity(0.3)) などを挟んでデバッグすると、どの段階でどのサイズになっているかが可視化できる。