SwiftUI のレイアウト優先度(layoutPriority)を使いこなす
SwiftUI のレイアウトシステムでは、スタック内の複数のビューが限られたスペースを奪い合う場面があります。layoutPriority は、どのビューがスペース配分で優先されるかを数値で指定するモディファイアです。デフォルトは 0 で、値が大きいほど優先的にスペースを割り当てられます。
スペースの奪い合い
まず、layoutPriority を使わない場合の挙動を確認しましょう。
HStack {
Text("長いテキストが入ります。非常に長い説明文です。")
.lineLimit(1)
.background(Color.blue.opacity(0.2))
Text("短いテキスト")
.lineLimit(1)
.background(Color.green.opacity(0.2))
}
.frame(width: 300)HStack の幅が足りない場合、SwiftUI は同じ優先度のビューにスペースを等分に配分しようとします。結果として、両方のテキストが中途半端に省略されることがあります。
layoutPriority で優先順位を設定する
HStack {
Text("長いテキストが入ります。非常に長い説明文です。")
.lineLimit(1)
.layoutPriority(1)
.background(Color.blue.opacity(0.2))
Text("短いテキスト")
.lineLimit(1)
.background(Color.green.opacity(0.2))
}
.frame(width: 300)左の Text に .layoutPriority(1) を設定すると、まず左のテキストがスペースを優先的に確保し、残りが右のテキストに割り当てられます。右のテキストが先に省略されるようになるため、重要な情報を確実に表示したい場面で役立ちます。
スペース配分の仕組み
layoutPriority によるスペース配分は段階的に行われます。
最も優先度の高いビューに必要なスペースを割り当てる
残ったスペースを次に優先度の高いビューに割り当てる
最も優先度の低いビューに残りのスペースを配分する
この段階的な配分が行われるため、優先度の高いビューはほぼ理想のサイズを確保でき、低いビューが圧縮を引き受けることになります。
実践例:ナビゲーションバー風レイアウト
タイトル、サブタイトル、アクションボタンが横並びの UI で、タイトルを優先して表示したいケースを考えてみましょう。
HStack(spacing: 8) {
VStack(alignment: .leading) {
Text("プロジェクト設定")
.font(.headline)
.lineLimit(1)
Text("詳細オプションを管理")
.font(.caption)
.foregroundColor(.secondary)
.lineLimit(1)
}
.layoutPriority(1)
Spacer()
Button("保存") { }
.buttonStyle(.borderedProminent)
}
.padding(.horizontal)VStack に .layoutPriority(1) を付けることで、テキスト部分が優先的にスペースを確保します。画面が狭くなっても「保存」ボタンのサイズが先に確定した後にテキスト領域にスペースが配分されるため、ボタンが押しつぶされることがありません。
複数の優先度レベル
layoutPriority は Double 型なので、3 段階以上の優先順位も設定できます。
HStack {
Text("高")
.layoutPriority(2)
.background(Color.red.opacity(0.2))
Text("中")
.layoutPriority(1)
.background(Color.yellow.opacity(0.2))
Text("低(デフォルト)")
.background(Color.gray.opacity(0.2))
}優先度 2 → 1 → 0(デフォルト)の順にスペースが配分されます。ただし、3 段階以上の優先度を使う場面はあまり多くありません。ほとんどのケースでは、特に重要なビューだけに .layoutPriority(1) を付ける 2 段階の運用で十分でしょう。
すべてのビューが同じ優先度(0)で、スペースが均等に配分される。どのビューが省略されるか予測しにくい
重要なビューに高い値を設定することで、スペース不足時に何が省略されるかを明示的にコントロールできる
fixedSize との違い
layoutPriority と fixedSize はどちらもスペース配分に関わりますが、アプローチが異なります。layoutPriority は「他のビューとの相対的な優先順位」を設定するのに対し、fixedSize は「親のサイズ提案を完全に無視して理想サイズを取る」という絶対的な指定です。
layoutPriority は親の提案を尊重しつつ配分の優先順位を変えるだけなので、レイアウトが予測しやすく安全に使えます。はみ出しのリスクがある fixedSize よりも、まず layoutPriority で解決できないかを検討するのがよいでしょう。