今回はHStack/VStackとLazyHStack/LazyVStack(ついでにScrollView)について説明していきます。
環境
- Xcode12.5.1
- iOS14.6
- スクショはiPhone12Pro Maxで撮影
HStack/VStack
HStack
はコンテンツを水平方向に並べていく、VStack
は垂直方向に並べていくレイアウトになります。
まずは HStack
でアイコンとテキストを水平方向に並べてみましょう。
struct ChildView: View {
var body: some View {
HStack {
Image("icon")
.resizable()
.frame(width: 90.0, height: 90.0, alignment: .center)
.clipShape(Circle())
Text("I'm talking about SwiftUI.")
.font(.system(size: 28.0))
}
}
}

iconを丸くしたりサイズを変えたりしていて少し見にくいですが、HStack
のクロージャの中に書いたオブジェクトが水平に並んでいるのがわかります。
このTextの上に名前を表示してみましょう。
struct ChildView: View {
var body: some View {
HStack {
Image("icon")
.resizable()
.frame(width: 90.0, height: 90.0, alignment: .center)
.clipShape(Circle())
VStack {
Text("Shuhey-H")
.font(.system(size: 14.0))
.fontWeight(.thin)
Text("I'm talking about SwiftUI.")
.font(.system(size: 28.0))
}
}
}
}

VStack
を使うことでTextの上に名前を表示できました。
ただ、中央寄せが気に入らないので、左寄せにしてみましょう。
struct ChildView: View {
var body: some View {
HStack {
Image("icon")
.resizable()
.frame(width: 90.0, height: 90.0, alignment: .center)
.clipShape(Circle())
VStack(alignment: .leading) {
Text("Shuhey-H")
.font(.system(size: 14.0))
.fontWeight(.thin)
Text("I'm talking about SwiftUI.")
.font(.system(size: 28.0))
}
}
}
}

VStack(alignment: .leading)
とすることで、その中のオブジェクトは左寄せになります。 同じように .trailing
を指定すると右寄せになります。何も指定しないor .center
を指定すると中央寄せになります。
ScrollView
さらにこのコンテンツを10個垂直に並べてみましょう。
struct ContentView: View {
var body: some View {
VStack {
ForEach(0..<10) { i in
ChildView()
}
}
}
}

ただ VStack
で並べただけなのでスクロールもできません。ScrolView
に入れましょう。
struct ContentView: View {
var body: some View {
ScrollView {
VStack {
ForEach(0..<10) { i in
ChildView()
}
}
}
}
}

とても簡単にスクロールが実装できました。
LazyHStack/LazyVStack
では10個ではなく100個、1000個とたくさん並べていくとどうなるでしょう?
もちろん1000個でも表示することはできます。しかし、VStack
は画面を表示する際に全てのコンテンツを生成し描画するという作りなので、数が多くなればなるほどメモリーへの負担が大きくなります。

VStackでただ1000個並べた場合は200MB近くメモリーを使用していますね。
ではこれを LazyVStack
にするとどうでしょう。

同じ1000個でもメモリーの使用は42.5MBとかなり抑えることができています。
これは LazyHStack/LazyVStack は画面に表示される分だけを生成する仕組みになっているからです。画面に映らない余計なものは生成しないことで、メモリーの使用を抑えることができます。
もちろんLazyをつけてもつけなくても見た目に違いはありません。
たくさんのオブジェクトを並べるときは LazyHStack/LazyVStack を使用することをお勧めします。
コメント
[…] HStack/VStackとLazyHStack/LazyVStack【SwiftUI】 […]