SwiftUIは、シンプルなコードでUIを構築できる強力なフレームワークです。
この記事では、これらのスタックの基本的な使い方と私が疑問に思った点を解説します。
その中でも、ビューを整理して配置するための基本的なツールとして「スタック(VStack、HStack、ZStack)」が提供されています。
各スタックにはそれぞれ内部に保持するViewの配置方法が変わります。
- VStack
- 「縦」方向に内部のViewを配置していきます
- HStack
- 「横」方向に内部のViewを配置していきます
- ZStack
- 「手前」方向に内部のViewを配置していきます
以下のコードは3種類のStackの内部で3つのTextを表示するコードになります。
それぞれのStackによる内部のViewの配置方法の違いがわかりやすいと思います。
struct ContentView: View {
var body: some View {
VStack{
VStack{
ForEach(1...3,id: \.self){ item in
Text("VStack:\(item)")
}
}
HStack{
ForEach(1...3,id: \.self){ item in
Text("HStack:\(item)")
}
}
ZStack{
ForEach(1...3,id: \.self){ item in
Text("HStack:\(item)")
}
}
}
}
}
#Preview() {
ContentView()
}
このコードのPreviewは以下の画像のようになります。
色のついている枠や文字は後からつけているものです。
気になったポイント
私が最初にひかかったのはこの点です。Swiftの言語としての機能を使って以下のようなコードでTextを配置しようとしたところエラーが発生しました。
なぜできるかと思ったのかというと、もともと「Kotlin + Jetpack Compose」でAndroidアプリを作成していたからです。
VStack{
for i in 1...3 {
Text("VStack:\(i)")
}
}
Closure containing control flow statement cannot be used with result builder 'ViewBuilder'
このエラーは「ViewBuilder」内で「制御フロー文」を使おうとした場合に発生するエラーのようです。
SwiftUIでは、「ForEach」を使うことで「ループ」をすることができるようです。つまりは関数を使えということですね。
VStack {
ForEach(1...3,id: \.self){ item in
Text("VStack:\(item)")
}
}
ただ指定した回数のループをさせるのにも、「id: \.self」という見慣れない引数をつけています。これの効果はまた別の記事で言及しようと思います。
とりあえずこの疑問の学びは以下の通りです。
「SwiftUIでは関数を使って制御をする」
各Stackを知らないうちは以下のようなコードを記述しては、「なんで縦に並ぶのか」と疑問に思っていました。
(想像では、整列されずに上に重なるイメージ)
struct ContentView: View {
var body: some View {
Text("test1")
Text("test2")
}
}
よくよく調べてみると、以下のような事がわかりました。
公式には「some View」にStack系を使わないで複数のViewを返すことを想定しているような記述はないので、複数のViewを使う場合は、Stackで包むのがいいと思います。
SwiftUIではbodyプロパティで複数のViewを帰す場合「@ViewBuilder」が自動的に適応され、1つのViewにまとめられる
ここで「@ViewBuilder」と何かわからないと思います。
私もわからないのでまた別の記事でまとめる予定です。
記事を公開できたら、リンクを貼る予定です。(とりあえず公式のドキュメントを今は貼っておきます)
以下のForm(質問)も参考になるかも?
struct ContentView: View {
var body: some View {
VStack{
// 深さを持ったスタック
ZStack(alignment: .bottom){
// 画像を表示(1番下)
Image("UserIcon")
.resizable() // 画像の横幅を画面に収まるように自動調整
.aspectRatio(contentMode: .fill)
.frame(height: 300)
.clipped() // frameからはみ出した部分をクリップ
HStack{
VStack(alignment: .leading){
Text("木村佳代子").font(.headline)
Text("スーパー唇赤い女").font(.subheadline)
}.padding() // 何も指定しないと4方向に16ポイント
// スペーサーで横いっぱいにHStackを広げる
Spacer()
}
// 前面で使う色を指定
.foregroundColor(.primary)
// 背景で使う色を前面で使う色の反転色に設定
.background(
Color.primary.colorInvert()
.opacity(0.75) // 少し透明にする
)
}
}
}
}
#Preview() {
ContentView()
}
SwiftUIはAndroidのJetpack Composeと比べて言語仕様をそのまま使うことができない部分がある反面、記述が少なくても作り込めるようにできているのが特徴だと感じました。
認識間違いや、不明な点がある場合はXかこの記事のコメント欄でご連絡ください。