พื้นฐานโพรโทคอล Layout
ใช้งาน sizeThatFits และ placeSubviews
พื้นฐานโพรโทคอล Layout เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน
เหตุใดจึงต้องใช้การจัดวางแบบกำหนดเอง
SwiftUI มี HStack, VStack และ ZStack มาให้ แต่บางครั้งคุณต้องใช้ตรรกะการจัดวางที่สิ่งเหล่านี้แสดงออกไม่ได้ เช่น เมนูวงกลม การจัดวางแบบไหล และตารางแบบก่ออิฐ
โปรโตคอลการจัดวางช่วยให้คุณเขียนตรรกะนั้นได้ พร้อมยังประกอบใช้งานร่วมกับมุมมอง SwiftUI ปกติ
โปรโตคอลการจัดวาง
Layout ต้องมีสองเมธอด ได้แก่ sizeThatFits (ฉันควรมีขนาดเท่าใด) และ placeSubviews (ลูกแต่ละตัวควรอยู่ที่ใด)
คุณทำให้ชนิดค่าเป็นไปตามโปรโตคอล แล้วใช้งานเหมือนสแตกในตัวทั่วไป
struct MyLayout: Layout {
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize { .zero }
func placeSubviews(in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) { }
}การใช้การจัดวางแบบกำหนดเอง
ค่าของ Layout ทำหน้าที่เป็นคอนเทนเนอร์ คุณส่งมุมมองลูกเข้าไปในคลอสเชอร์ต่อท้ายของมันได้เหมือนกับสแตก
var body: some View {
MyLayout {
Text("One")
Text("Two")
Text("Three")
}
}ProposedViewSize
มุมมองแม่เสนอขนาดให้การจัดวางของคุณผ่าน ProposedViewSize ค่า width และ height เป็นค่าทางเลือก โดย nil หมายถึง "ไม่ได้ระบุ ให้เลือกขนาด ideal ของคุณเอง"
ค่าพิเศษ .zero, .infinity และ .unspecified ใช้ตรวจสอบขนาดต่ำสุด สูงสุด และ ideal ตามลำดับ
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize {
let width = proposal.width ?? 0
return CGSize(width: width, height: 44)
}sizeThatFits โดยละเอียด
sizeThatFits คืนค่าขนาดที่การจัดวางของคุณต้องการเมื่อได้รับข้อเสนอขนาดหนึ่ง SwiftUI อาจเรียกเมธอดนี้หลายครั้งด้วยข้อเสนอที่แตกต่างกัน เพื่อทำความเข้าใจความยืดหยุ่นของคุณ
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize {
// Sum child ideal sizes for a simple horizontal stack
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
let w = sizes.reduce(0) { $0 + $1.width }
let h = sizes.map(\.height).max() ?? 0
return CGSize(width: w, height: h)
}คอลเลกชันของมุมมองย่อย
Subviews คือคอลเลกชันของพร็อกซีสำหรับลูกแต่ละตัว พร็อกซีแต่ละตัวตอบ sizeThatFits และเปิดเผยลำดับความสำคัญของการจัดวางกับค่ากำหนดเอง
คุณจะไม่เห็นมุมมองจริง แต่จะเห็นเพียงพร็อกซีสำหรับการวัดขนาดเหล่านี้
for subview in subviews {
let size = subview.sizeThatFits(.unspecified)
print(size)
}placeSubviews
placeSubviews กำหนดตำแหน่งให้ลูกแต่ละตัวภายในสี่เหลี่ยม bounds ที่ส่งให้คุณ
เรียก place(at:anchor:proposal:) บนพร็อกซีของมุมมองย่อยแต่ละตัว
func placeSubviews(in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) {
var x = bounds.minX
for subview in subviews {
let size = subview.sizeThatFits(.unspecified)
subview.place(at: CGPoint(x: x, y: bounds.midY),
anchor: .leading,
proposal: .unspecified)
x += size.width
}
}จุดยึดขณะวาง
พารามิเตอร์ anchor ระบุว่าจุดใดของลูกจะตรงกับตำแหน่งที่คุณกำหนด .topLeading จะวางโดยใช้มุมซ้ายบน ส่วน .center จะจัดลูกให้อยู่กึ่งกลางตรงตำแหน่งนั้น
subview.place(at: CGPoint(x: 0, y: 0),
anchor: .topLeading,
proposal: .unspecified)ขอบเขตไม่ได้อยู่ที่จุดกำเนิดเสมอไป
สี่เหลี่ยม bounds อาจไม่ได้เริ่มต้นที่ (0,0) ให้จัดตำแหน่งโดยอ้างอิงจาก bounds.minX และ bounds.minY เสมอ อย่าใช้ศูนย์สัมบูรณ์
let startX = bounds.minX // not 0
let startY = bounds.minYการจัดวางแบบเว้นระยะเท่ากันอย่างง่าย
เมื่อนำทุกอย่างมารวมกัน นี่คือการจัดวางที่วางลูกจากซ้ายไปขวาโดยไม่มีระยะห่าง เมธอดทั้งสองยังคงสอดคล้องกัน ขนาดที่รายงานตรงกับตำแหน่งที่วาง
struct SimpleHStack: Layout {
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
return CGSize(width: sizes.reduce(0){ $0 + $1.width },
height: sizes.map(\.height).max() ?? 0)
}
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
var x = bounds.minX
for s in subviews {
let size = s.sizeThatFits(.unspecified)
s.place(at: CGPoint(x: x, y: bounds.minY), anchor: .topLeading, proposal: .unspecified)
x += size.width
}
}
}คุณต้องรักษาความสอดคล้อง
SwiftUI เชื่อว่าเมธอดทั้งสองของคุณให้ผลสอดคล้องกัน หาก placeSubviews ใช้พื้นที่มากกว่าที่ sizeThatFits รายงาน ลูกอาจถูกตัดหรือซ้อนทับกัน
ใช้การคำนวณเรขาคณิตชุดเดียวกันร่วมกันในเมธอดทั้งสอง
ตรวจสอบความเข้าใจ: พื้นฐานการจัดวาง
ทดสอบความเข้าใจของคุณเกี่ยวกับโปรโตคอลการจัดวาง
สรุป: พื้นฐานโปรโตคอลการจัดวาง
โปรโตคอล Layout เปลี่ยนตรรกะการจัดวางแบบกำหนดเองให้เป็นคอนเทนเนอร์ที่นำกลับมาใช้ใหม่ได้ sizeThatFits รายงานขนาดของคุณสำหรับ ProposedViewSize และ placeSubviews จัดตำแหน่งพร็อกซีของลูกแต่ละตัวภายใน bounds โดยใช้ place(at:anchor:proposal:)
ข้อเสนอจะมีมิติที่เป็นค่าทางเลือก ขอบเขตอาจมีจุดเริ่มต้นเยื้องจากจุดกำเนิด และเมธอดทั้งสองต้องรักษาความสอดคล้องทางเรขาคณิต ต่อไปเราจะวัดขนาดมุมมองย่อยในรายละเอียด
คำถามที่พบบ่อย
บทเรียน “พื้นฐานโพรโทคอล Layout” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “พื้นฐานโพรโทคอล Layout” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “พื้นฐานโพรโทคอล Layout”
ใช้งาน sizeThatFits และ placeSubviews คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “พื้นฐานโพรโทคอล Layout” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม
ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- พื้นฐานโพรโทคอล Layout
- การวัดมุมมองย่อย
- การสร้างการจัดวางแบบไหล
- แคชการจัดวางและประสิทธิภาพ