【ITニュース解説】Understanding SwiftUI Stacks: HStack, VStack, and ZStack - A Deep Dive

2025年09月04日に「Dev.to」が公開したITニュース「Understanding SwiftUI Stacks: HStack, VStack, and ZStack - A Deep Dive」について初心者にもわかりやすいように丁寧に解説しています。

作成日: 更新日:

ITニュース概要

SwiftUIのレイアウトはHStack(水平)、VStack(垂直)、ZStack(奥行き)の3つのStackで構成される。HStackは要素を横に、VStackは縦に、ZStackは重ねて配置する。iOS16以降ではLayoutプロトコルに準拠し、サイズ提案、子要素の測定、配置の3段階でレイアウトが決定。優先度に応じてスペースが分配される。

ITニュース解説

SwiftUIにおけるレイアウトの基本は、HStack、VStack、ZStackという3つのコンテナビューだ。これらを理解することで、複雑なUIもシンプルに構築できる。

HStackは、要素を水平方向に並べる。左から右へ、または先頭から末尾へという並び順になる。例えば、複数のテキストを横一列に表示したい場合にHStackを使う。

VStackは、要素を垂直方向に並べる。上から下へという並び順になる。テキストや画像を縦に積み重ねて表示したい場合にVStackが適している。

ZStackは、要素を深度方向に重ねて表示する。最初に記述した要素が一番下に、後から記述した要素が上に重なる。背景の上にテキストを重ねたり、複数の画像を重ねて表示したりする際に使用する。

これらのStackは、SwiftUIのLayoutプロトコルに準拠している。レイアウト処理は、サイズ提案フェーズ、子要素計測フェーズ、配置フェーズの3段階で行われる。サイズ提案フェーズでは、親ビューがStackにサイズを提案する。子要素計測フェーズでは、Stackが各子要素に理想的なサイズを問い合わせる。配置フェーズでは、Stackが各子要素を割り当てられた領域内に配置する。

HStackは、子要素の理想的な幅の合計と要素間の間隔を基に必要な最小幅を計算する。余分なスペースがある場合は、各子要素のレイアウト優先度に基づいて分配する。Spacerなどのフレキシブルな要素は、利用可能なスペースを埋めるように拡張する。VStackも同様の仕組みで、高さに基づいてスペースを分配する。ZStackは、すべての子要素を包含できるサイズを決定し、デフォルトでは各子要素を中央に配置する。ZStackではスペースの分配は行われず、すべての子要素が利用可能な領域全体を使用できる。

SwiftUIでは、レイアウト優先度を使用してスペースの分配方法を決定する。優先度が高い要素は、より多くのスペースを最初に取得する。デフォルトの優先度は0で、標準的なスペース配分が行われる。優先度が低い要素は、残りのスペースを取得する。.layoutPriority() modifierで優先度を変更できる。

要素の拡張と縮小の挙動は、Stackの種類によって異なる。HStackでは、水平方向には、固定サイズの要素がまず必要な幅を取得し、フレキシブルな要素が残りのスペースを均等に分割する。垂直方向には、デフォルトではHStackの高さは最も高い子要素の高さに合わせられ、すべての子要素が垂直方向に拡張して最大の要素に合わせることができる。VStackでは、垂直方向のスペース配分がHStackと同様に行われ、水平方向には、デフォルトでVStackの幅は最も幅の広い子要素の幅に合わせられる。ZStackは、すべての子要素を包含するために必要なサイズを決定する。各子要素は互いのサイズに影響を与えず、それぞれが独立したサイズを持つことができる。ZStack自体は、最も大きな子要素に合わせて拡張する。

パフォーマンスを考慮すると、Stackのネストはできるだけ避けるべきだ。ネストが深くなるほど、計算コストが増加する。大きなコレクションを扱う場合は、LazyHStackやLazyVStackを使用すると、表示されているアイテムのみがレンダリングされるため、パフォーマンスが向上する。条件付きでコンテンツを表示する場合は、複数のStackを使用する代わりに、@ViewBuilderを使用する方が効率的だ。.fixedSize() modifierを適切に使用すると、不要なレイアウトの再計算を避けることができる。

HStackとVStackは、すべての子要素をすぐにロードするが、LazyHStackとLazyVStackは、必要に応じて子要素をロードする。ZStackは、常にすべてのレイヤーをメモリに保持するため、メモリ使用量に注意する必要がある。

Stackには、要素の配置を制御するためのアライメントオプションが用意されている。HStackでは、.top.center.bottom.firstTextBaselineなどの垂直方向のアライメントを指定できる。VStackでは、.leading.center.trailingなどの水平方向のアライメントを指定できる。ZStackでは、両方の軸のアライメントを組み合わせることができる。

要素間の間隔は、spacingパラメータで制御できる。Spacerを使用すると、フレキシブルな間隔を作成できる。

レスポンシブなレイアウトを作成するには、GeometryReaderとStackを組み合わせる。GeometryReaderを使用して画面サイズを取得し、サイズに応じてHStackまたはVStackを使用する。

Stackのレイアウトをデバッグするには、.border().background()などのmodifierを使用して、ビューの境界線や占有スペースを可視化すると便利だ。また、GeometryReaderと.overlay()を組み合わせて、実際の寸法を表示することもできる。

関連コンテンツ

【ITニュース解説】Understanding SwiftUI Stacks: HStack, VStack, and ZStack - A Deep Dive | いっしー@Webエンジニア