SwiftUIではStackと呼ばれる部品配置用のViewを組み合わせて、レイアウトを作成します。
本記事では3つのStack View(VStack、HStack、ZStack)を中心にレイアウト方法を解説します。
環境
この記事の情報は次のバージョンで動作確認しています。
【Swift】5.1
【iOS】13.2.2
【macOS】Catalina バージョン 10.15.2
Stack Viewの基本的な使い方
SwiftUIには次の3種類のStack Viewがあります。
- 縦に並べるVStack()
- 水平に並べるHStack()
- 重ねて配置するZStack()
VStack
内包する子Viewを縦に配置するStack Viewです。
1 2 3 4 5 6 7 |
VStack(alignment: 配置方法, spacing: 子View同士の間隔) { // 引数は省略可能 子View1 子View2 ︙ } |
使用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
struct ContentView: View { var body: some View { VStack { Text("カピ通信") .font(.largeTitle) .frame(width:150) .background(Color.blue) Text("SwiftUI") .font(.largeTitle) .frame(width:200) .background(Color.green) } } } |
HStack
内包する子Viewを水平に配置するStack Viewです。
1 2 3 4 5 6 7 |
HStack(alignment: 配置方法, spacing: 子View同士の間隔) { // 引数は省略可能 子View1 子View2 ︙ } |
使用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
struct ContentView: View { var body: some View { HStack { Text("SwiftUI") .font(.largeTitle) .frame(width:150) .background(Color.green) Text("Apple") .font(.largeTitle) .frame(width:200) .background(Color.yellow) } } } |
子View間の間隔は標準でシステムデフォルト値が採用されます。
VStackの時と異なり、2つのViewの間に隙間があるのがわかります。
間隔を明示的に指定する場合は、spacing引数で指定します。
ZStack
内包する子Viewを重ねて配置するStack Viewです。
指定した順に後ろから前に描画します。
1 2 3 4 5 6 7 |
ZStack(alignment: 配置方法) { // 引数は省略可能 子View 子View ︙ } |
使用例
Image ViewにText Viewを重ねる例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
struct ContentView: View { var body: some View { ZStack { Image("capibara") .resizable() .scaledToFit() Text("カピ通信") .font(.largeTitle) .frame(width:150) .background(Color.blue) } } } |
組み合わせ
Stackを組合わせて使い、より複雑なレイアウトを組み立てられます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
struct ContentView: View { var body: some View { ZStack { Image("capibara") .resizable() .scaledToFit() VStack { Text("カピ通信") .font(.largeTitle) .frame(width:150) .background(Color.blue) HStack { Text("SwiftUI") .font(.largeTitle) .frame(width:150) .background(Color.green) Text("Apple") .font(.largeTitle) .frame(width:200) .background(Color.yellow) } } } } } |
子Viewを11個以上並べる場合
SwiftUIでは、並べるViewの数は10個までの制限がありますので、それ以上の子Viewを並べたい場合は、
こちらの記事で解説している方法を使用して下さい。
配置方法の指定(alignment)
Stack Viewではalignment引数によって子Viewの配置方法を指定できます。
各々指定できる値が異なります。
1 2 3 4 5 |
VStack(alignment: 配置方法) 水平方向の配置方法を指定 HStack(alignment: 配置方法) 垂直方法の配置方法を指定 ZStack(alignment: 配置方法) 重ねるViewの配置方法を指定 |
VStackでの配置指定
配置方法 | 意味 |
---|---|
.center | 中央寄せ(デフォルト値) |
.leading | 左寄せ |
.trailing | 右寄せ |
使用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
struct ContentView: View { var body: some View { VStack(alignment: .leading) { // 左寄せ Text("カピ通信") .font(.largeTitle) .frame(width: 150) .background(Color.blue) Text("SwiftUI") .font(.largeTitle) .frame(width: 200) .background(Color.green) } } } |
HStackでの配置指定
配置方法 | 意味 |
---|---|
.top | 上寄せ |
.center | 中央寄せ(デフォルト値) |
.bottom | 下寄せ |
使用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
struct ContentView: View { var body: some View { VStack { HStack(alignment: .bottom) { // 下寄せ Text("SwiftUI") .font(.headline) .frame(width:150) .background(Color.green) Text("Apple") .font(.largeTitle) .frame(width:200) .background(Color.yellow) } } } } |
ZStackでの配置指定
配置方法 | 意味 |
---|---|
.center | 中央寄せ(デフォルト値) |
.bottom | 下寄せ |
.bottomLeading | 左下寄せ |
.bottomTrailing | 右下寄せ |
.leading | 左寄せ |
.top | 上寄せ |
.topLeading | 左上寄せ |
.topTrailing | 右上寄せ |
.trailing | 右寄せ |
使用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
struct ContentView: View { var body: some View { ZStack(alignment: .topTrailing) { // 右上寄せ Image("capibara") .resizable() .scaledToFit() Text("カピ通信") .font(.largeTitle) .frame(width:150) .background(Color.blue) } } } |
Viewの表示位置をずらす(offset)
1 2 3 |
.offset(x: 水平方向にずらす距離, y: 垂直方向にずらす距離) |
配置したViewを指定した距離だけずらして表示します。
あくまで表示をずらすだけで、レイアウトの基準となるフレーム位置はそのままですので、注意してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
struct ContentView: View { var body: some View { ZStack(alignment: .topTrailing) { Image("capibara") .resizable() .scaledToFit() Text("カピ通信") .font(.largeTitle) .frame(width:150) .background(Color.blue) .offset(x: -50, y: 50) // 表示をずらす .border(Color.red, width: 2) // フレームを可視化 } } } |
Viewの間隔指定(spacing)
VStackとHStackでは子View同士の間隔を引数spacingで調整できます。
1 2 3 4 |
VStack(spacing: 間隔) HStack(spacing: 間隔) |
マイナス値の設定も可能です。
デフォルト値はnilで、この場合システムデフォルトの間隔が採用されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
struct ContentView: View { var body: some View { VStack(spacing: -10) { // 垂直方法の間隔を-10に設定 Text("カピ通信") .font(.largeTitle) .frame(width:150) .background(Color.blue) HStack(spacing: 80) { // 水平方向の間隔を80に設定 Text("SwiftUI") .font(.largeTitle) .frame(width:150) .background(Color.green) Text("Apple") .font(.largeTitle) .frame(width:200) .background(Color.yellow) } } } } |
空白を入れる(Spacer)
VStackおよびHStackでは、子Viewはデフォルトで使用可能なスペースの中央に配置されます。
これを変更したい場合は、Spacer()を使用して、スタックの内容を片側に寄せられます。Spacer()は残りのすべてのスペースを自動的に占有するため、例えばVStackの最後に追加すると、すべてのViewが画面の上部に寄せられます。
複数のSpacer()を追加すると、Spacer()が使用可能なスペースを分割します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
struct ContentView: View { var body: some View { VStack { Text("カピ通信") .font(.largeTitle) .frame(width:150) .background(Color.blue) Text("SwiftUI") .font(.largeTitle) .frame(width:200) .background(Color.green) Spacer() // 一番下側にスペースを配置する } } } |
最小値の指定
1 2 3 |
Spacer(minLength: CGFloat?) |
引数(minLength)で確保するスペースの最小値を指定します。
例えば、同じ軸に複数のSpacerがあった場合、通常は均等にスペースが割り振られますが、このイニシャライザで最低限確保したいスペースを指定する事ができます。
仕切り線を入れる(Divider)
VStackおよびHStackでは、Divider()を使って子Viewの間に仕切り線を挿入できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
struct ContentView: View { var body: some View { VStack { Text("カピ通信") .font(.largeTitle) .frame(width:150) .background(Color.blue) Divider() // 仕切り線の挿入 HStack { Text("SwiftUI") .font(.largeTitle) .frame(width:150) .background(Color.green) Divider() // 仕切り線の挿入 Text("Apple") .font(.largeTitle) .frame(width:200) .background(Color.yellow) } } } } |
仕切り線自体が表示可能な最大長で挿入される為、元のレイアウトが崩れる要因になりかねず、使用にあたっては注意が必要です。