Sponsor Link
環境&対象
- macOS Monterery beta 4
- Xcode 13 beta4
- iOS 15 beta
SwiftUI の レイアウト
SwiftUI でどのようにレイアウトされるかを確認するために、シンプルな例から見ていきます。
シンプルな例
一番シンプルな例から見ていきます。
//
// LayoutApp.swift
//
// Created by : Tomoaki Yagishita on 2021/07/29
// © 2021 SmallDeskSoftware
//
import SwiftUI
@main
struct LayoutApp: App {
var body: some Scene {
WindowGroup {
Text("Hello, world!")
}
}
}
Hello, world! というテキストを表示するアプリです。
親ビュー と 子ビュー のやりとり
このとき、親ビュー(WindowGroup)と子ビュー(Text) とは、以下のようなやりとりがされています。
以下の例では、デバイスとして iPhone11 が使われたケースで説明しています。
sequenceDiagram autonumber WindowGroup->>Text: おすすめサイズは(414.0 x 814.0)だけど, 必要なサイズは? Text->>WindowGroup: (94.5 x 20.5) あれば、良いです WindowGroup-->>WindowGroup: Text を配置しよう
上記のやり取りを通して、レイアウトが確定します。
- WindowGroup が渡すサイズは、iPhone11 のスクリーンサイズです
- Text は、”Hello, world!” を配置するのに必要なサイズ(94.5×20.5)を返します
- WindowGroup は、Text から受け取った情報をもとに配置します
- 一番 Root にあるためにスクリーンサイズ全体が渡されます
- Text は、自分が必要とする以上に領域を使用しない pull-in タイプのビューであるため、上位から自分が必要とするサイズより大きな値を渡されても、余分に領域を確保するような振る舞いはとりません
- ドキュメントに明確な記載はありませんが、WindowGroup は、子ビューを領域の中心に配置するようです
上記のレイアウト作業の結果として、画面中央に、テキストにちょうどのサイズで Hello, world! が表示される結果となります。
Note: WindowGroup は、1つのビューしか子要素として持ちません。
どうやって、おすすめサイズの値や実際の Text のサイズを確認するのか
サンプルのコードでは内部でやり取りされて処理されてしまうために、そのままでは親ビュー(WindowGroup)からの提案したサイズや子ビュー(Text) の返したサイズは確認できません。
レイアウト確認につかう GeometryReader
GeometryReader という便利なビューがあります。Apple のドキュメントは、こちら。
この GeometryReader には、上位ビューから提案されたサイズが渡されます。
.background 内で使用されると .backgroud が対象としているビューがもつサイズが渡されてきます。
以下のようにすることで、WindowGroup から Text に提案されるサイズ と Text が使用するサイズ を確認することができます。
//
// LayoutApp.swift
//
// Created by : Tomoaki Yagishita on 2021/07/29
// © 2021 SmallDeskSoftware
//
import SwiftUI
@main
struct LayoutApp: App {
var body: some Scene {
WindowGroup {
// (1)
GeometryReader { geom in
Text("Hello, world!")
.background(
// (2)
GeometryReader{ geom in
Color.clear
// (3)
.debugPrint("size in background: \(geom.size)")
})
// (4)
.debugPrint("size from GeometryReader:\(geom.size)")
}
}
}
}
- WindowGroup が Text に提案するサイズを確認するために、その間に入るように GeometryReader を配置します
- Text に付与した .background 内に GeometryReader を配置することで、Text が使用するサイズを確認できます
- (2) で定義した サイズ を print しています
- (1) で渡された サイズ を print しています
Xcode のコンソールには 以下のようにプリントされます。
size from GeometryReader:(414.0, 814.0)
size in background: (94.5, 20.5)
なお、GeometryReader を WindowGroup と Text の間に入れたため、最初の例とは異なり、以下のようなレイアウトになります。
これは、GeometryReader の子ビューをレイアウトする方法が WindowGroup とは異なるからです。
レイアウト決定時の注記事項
レイアウト決定時には、以下のようなルールが適用されています。
- 親ビューは、サイズを提案できるが、決定するのは子ビューであり、その値を親ビューは変更できない
- 子ビューをどこに配置するかは親ビューが決定することで、子ビューは関与できない
- 親ビューは、子ビューを配置するときに 子ビュー向けに確保した領域で子ビュー全体が表示できるかどうかは気にしない
次回以降で、上記のルールを 実例を見ながら確認していきます。
[SwiftUI] SwiftUI の layout システムを理解する (準備編: border と GeometryReader )
[SwiftUI] SwiftUI の layout システムを理解する ( .frame の働き)
[SwiftUI] SwiftUI の layout システムを理解する (push-out タイプビュー, pull-in タイプビュー とレイアウトの調整)
[SwiftUI] SwiftUI の layout システムを理解する (push-out タイプビューの調停)
[SwiftUI] SwiftUI の layout システムを理解する (コンテナビューに含まれる push-out / pull-in タイプビューの調停)
[SwiftUI] SwiftUI の layout システムを理解する (領域が不足するケースの調停)
[SwiftUI] SwiftUI の layout システムを理解する (Text)
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
Sponsor Link