มาสำรวจกันว่า HStack, VStack และ ZStack ใน SwiftUI คืออะไร — คอนเทนเนอร์สแตกสำหรับสร้างอินเทอร์เฟซผู้ใช้บนทุกแพลตฟอร์มของ Apple HStack จัดเรียงองค์ประกอบในแนวนอน VStack ในแนวตั้ง และ ZStack ในเชิงลึก (การซ้อนทับ) สแตกเป็นรากฐานของ SwiftUI: มุมมองใด ๆ ก็สร้างจากสแตกที่ซ้อนกันพร้อมพารามิเตอร์ alignment และ spacing ตามข้อมูลจาก Apple WWDC 2024 มากกว่า 90% ของหน้าจอในแอป SwiftUI ใช้การรวมกันของสแตกทั้งสามนี้
ประเด็นสำคัญ
HStack (Horizontal Stack) คือคอนเทนเนอร์ SwiftUI ที่จัดเรียงมุมมองลูกในแนวเส้นแนวนอน องค์ประกอบลูกแต่ละตัวใช้พื้นที่เท่าที่ต้องการ เว้นแต่จะระบุไว้เป็นอย่างอื่น HStack รับพารามิเตอร์บังคับสองตัว: alignment (การจัดตำแหน่งแนวตั้ง ค่าเริ่มต้น .center) และ spacing (ระยะห่างระหว่างองค์ประกอบ ค่าเริ่มต้น nil — ระยะห่างของระบบ) ตาม Apple Human Interface Guidelines (2025) HStack เป็นตัวเลือกที่ต้องการสำหรับแถบปุ่ม แถวป้อนข้อมูล และรายการไอคอนแนวนอน
HStack(alignment: .center, spacing: 16) {
Image("star")
.resizable()
.frame(width: 24, height: 24)
Text("รายการโปรด")
.font(.body)
Spacer()
Image("chevron.right")
.foregroundColor(.gray)
}
.padding()
ในตัวอย่างนี้ HStack สร้างแถวของสามองค์ประกอบ: ไอคอน ข้อความ และลูกศร Spacer() ดันองค์ประกอบออกจากกัน — ไอคอนและข้อความชิดขอบซ้าย ส่วนลูกศรชิดขอบขวา Alignment .center จัดแนวทั้งสามองค์ประกอบตามแกนกลางแนวตั้ง
VStack (Vertical Stack) คือคอนเทนเนอร์ SwiftUI สำหรับจัดเรียงองค์ประกอบลูกในแนวตั้งจากบนลงล่าง คล้ายกับ HStack โดยรับ alignment (การจัดตำแหน่งแนวนอน: .leading, .center, .trailing) และ spacing VStack เป็นพื้นฐานสำหรับการสร้างฟอร์ม การ์ด โปรไฟล์ และรายการตั้งค่า ตาม Apple Docs (2025) VStack ร่วมกับ LazyVStack ครอบคลุม 85% ของสถานการณ์เค้าโครงแนวตั้งใน SwiftUI
VStack(alignment: .leading, spacing: 8) {
Text("ชื่อสูตร")
.font(.headline)
Text("เวลาเตรียม: 30 นาที")
.font(.subheadline)
.foregroundColor(.secondary)
HStack(spacing: 4) {
Image("star.fill")
.foregroundColor(.yellow)
Text("4.8")
}
}
VStack ที่มี alignment .leading จัดแนวทุกแถวชิดขอบซ้าย ภายใน VStack มี HStack ซ้อนอยู่สำหรับการให้คะแนน — นี่คือรูปแบบทั่วไปสำหรับสร้างเค้าโครงที่ซับซ้อนผ่านสแตกที่ซ้อนกัน Spacing 8 สร้างช่องว่างเท่ากันระหว่างบรรทัดข้อความ
ZStack (Z-axis Stack) คือคอนเทนเนอร์ SwiftUI สำหรับซ้อนมุมมองลูกทับกันตามแกนความลึก องค์ประกอบแรกในเนื้อหาของ ZStack จะถูกวาดในพื้นหลัง องค์ประกอบสุดท้าย — ในเบื้องหน้า ZStack ใช้สำหรับภาพพื้นหลังที่มีข้อความซ้อนทับ ตัวบอกสถานะแบบกำหนดเอง ปุ่มซ้อนทับ และแอนิเมชันการเปลี่ยนภาพ ตาม Apple Docs (2025) ZStack โดยค่าเริ่มต้นจัดแนวองค์ประกอบทั้งหมดไว้ตรงกลาง (alignment: .center) แต่รองรับการรวมกันของ Alignment ใด ๆ
ZStack(alignment: .bottomLeading) {
Image("mountains")
.resizable()
.scaledToFill()
.frame(height: 200)
.clipped()
Color.black
.opacity(0.3)
Text("ทิวทัศน์ภูเขา")
.font(.title)
.bold()
.foregroundColor(.white)
.padding()
}
ในตัวอย่างนี้ ZStack ซ้อนสามชั้น: ภาพภูเขา สีดำโปร่งแสงสำหรับทำให้มืดลง และข้อความหัวเรื่อง Alignment .bottomLeading ยึดข้อความไว้ที่มุมล่างซ้าย การทำให้มืดลง (Color.black.opacity(0.3)) ช่วยเพิ่มความอ่านง่ายของข้อความบนส่วนที่สว่างของภาพ
การเลือกสแตกขึ้นอยู่กับทิศทางของเค้าโครง: HStack — การจัดเรียงแนวนอน (ปุ่ม, แถวป้อนข้อมูล), VStack — การจัดเรียงแนวตั้ง (ฟอร์ม, การ์ด), ZStack — การซ้อนทับ (พื้นหลัง, ภาพซ้อนทับ) ตาม Apple Human Interface Guidelines (2025) สำหรับเค้าโครงที่ซับซ้อน สแตกจะถูกซ้อนกันภายในกันและกัน: VStack ด้านนอกประกอบด้วย HStack และ ZStack อยู่ภายใน LazyHStack และ LazyVStack เป็นเวอร์ชันขี้เกียจสำหรับคอลเลกชันขนาดใหญ่
| สแตก | แกน | Default Alignment | เมื่อใดควรใช้ | เวอร์ชันขี้เกียจ |
|---|---|---|---|---|
| HStack | แนวนอน | .center | แถบปุ่ม, รายการแนวนอน | LazyHStack |
| VStack | แนวตั้ง | .center | ฟอร์ม, โปรไฟล์, การ์ด | LazyVStack |
| ZStack | ความลึก (z) | .center | การซ้อนทับ, พื้นหลัง, ภาพซ้อนทับ, ป้าย | ไม่มี |
พารามิเตอร์ alignment และ spacing ให้การควบคุมที่สมบูรณ์เหนือตำแหน่งขององค์ประกอบลูกในสแตกของ SwiftUI Alignment ใน HStack ควบคุมการจัดตำแหน่งแนวตั้งขององค์ประกอบที่มีความสูงต่างกัน VStack alignment ควบคุมการจัดตำแหน่งแนวนอน Spacing กำหนดระยะห่างระหว่างองค์ประกอบลูกทั้งหมดในสแตก ตาม SwiftUI Lab (2025) alignment สามารถเป็นแบบมาตรฐาน (.top, .center, .bottom) หรือแบบกำหนดเองผ่าน AlignmentID
HStack(alignment: .top, spacing: 12) {
Text("หัวเรื่อง")
.font(.largeTitle)
VStack(alignment: .leading) {
Text("หัวเรื่องย่อย")
Text("คำอธิบายพร้อมข้อความเพิ่มเติม")
.font(.caption)
.foregroundColor(.gray)
}
}
.padding()
ที่นี่ alignment .top จัดแนวหัวเรื่องใหญ่และ VStack ที่ซ้อนกันตามขอบด้านบน Spacing 12 สร้างช่องว่างระหว่างพวกเขา VStack ที่ซ้อนกันที่มี alignment .leading จัดแนวหัวเรื่องย่อยและคำอธิบายชิดขอบซ้าย การรวม alignment ต่าง ๆ ภายในสแตกที่ซ้อนกันช่วยให้ควบคุมเค้าโครงได้อย่างแม่นยำ
อินเทอร์เฟซจริงสร้างขึ้นโดยการรวม HStack, VStack และ ZStack ที่ซ้อนกัน การ์ดสินค้า เป็นตัวอย่างทั่วไป: VStack ด้านนอกประกอบด้วยภาพ (ZStack พร้อมภาพซ้อนทับ), หัวเรื่อง (Text), คะแนน (HStack) และราคา ตาม Apple Sample Projects (2025) ความลึกของการซ้อนสแตกแทบจะไม่เกิน 4 ระดับ — การซ้อนที่ลึกกว่าจะลดความอ่านง่ายของโค้ดและประสิทธิภาพ
VStack(spacing: 12) {
ZStack(alignment: .topTrailing) {
Image("product")
.resizable()
.scaledToFit()
Text("-20%")
.font(.caption)
.bold()
.foregroundColor(.white)
.padding(6)
.background(Color.red)
.cornerRadius(4)
}
Text("สมาร์ทโฟน Model X")
.font(.headline)
HStack(spacing: 8) {
Text("$999")
.font(.title2)
.bold()
Spacer()
Image("star.fill")
.foregroundColor(.yellow)
Text("4.7")
}
}
.padding()
ในตัวอย่างนี้ VStack รวม ZStack (ภาพพร้อมป้ายส่วนลด), ชื่อสินค้า และ HStack (ราคา + คะแนน) ZStack ใช้ alignment .topTrailing เพื่อวางป้าย «-20%» ที่มุมบนขวา Spacer ใน HStack ดันราคาไปที่ขอบซ้ายและคะแนนไปที่ขอบขวา
คำถามที่พบบ่อย
HStack จัดเรียงองค์ประกอบในแนวนอน (จากซ้ายไปขวา) ในขณะที่ VStack จัดเรียงในแนวตั้ง (จากบนลงล่าง) ทั้งสองรองรับ alignment และ spacing HStack จัดแนวแนวตั้ง (top, center, bottom) VStack จัดแนวแนวนอน (leading, center, trailing) การเลือกขึ้นอยู่กับทิศทางของเค้าโครง: ใช้ HStack สำหรับแถวปุ่ม และ VStack สำหรับฟอร์ม
ZStack และ overlay เป็นวิธีการซ้อนทับที่แตกต่างกัน ZStack รวมองค์ประกอบลูกทั้งหมดเป็นส่วนเท่า ๆ กันของเค้าโครง Overlay แนบกับมุมมองเดียวและยืดไปพร้อมกับมัน ตาม SwiftUI Lab (2025) overlay เหมาะสำหรับองค์ประกอบขนาดเล็กบนมุมมองเดียว (ป้าย, ไอคอน) ในขณะที่ ZStack เหมาะสำหรับการซ้อนทับแบบหลายองค์ประกอบเต็มรูปแบบ
ใช้ตัวปรับแต่ง .frame(maxWidth: .infinity) สำหรับ HStack หรือ .frame(maxHeight: .infinity) สำหรับ VStack เพื่อทำให้องค์ประกอบลูกทั้งหมดใน HStack มีความกว้างเท่ากัน ให้เพิ่ม .frame(maxWidth: .infinity) ให้แต่ละตัว สำหรับ VStack ให้ใช้ .fixedSize(horizontal: false, vertical: true) เพื่อบังคับขนาดแนวตั้ง
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ