Expanded คือวิดเจ็ต Flutter ที่บังคับให้องค์ประกอบลูกเติมเต็มพื้นที่ว่างทั้งหมดในคอนเทนเนอร์ Flex เมื่อ Row หรือ Column กระจายพื้นที่ระหว่างลูก ๆ Expanded จะนำพื้นที่ว่างหลังจากคำนวณองค์ประกอบที่ไม่ยืดหยุ่นแล้ว ตามเอกสารอย่างเป็นทางการของ Flutter (2026) Expanded เป็นหนึ่งในวิดเจ็ตเลย์เอาต์ที่ใช้มากที่สุด: มันถูกใช้ในอินเทอร์เฟซแบบเปอร์เซ็นต์ การสร้างการ์ด รายการ และแผง ข้อได้เปรียบหลักคือการคำนวณความกว้างหรือความสูงโดยอัตโนมัติตามค่าสัมประสิทธิ์ flex โดยไม่ต้องระบุขนาดอย่างชัดเจน
ประเด็นสำคัญ
Expanded คือวิดเจ็ตห่อหุ้มที่รับลูกและบังคับให้มันขยายเพื่อเติมเต็มพื้นที่ว่างในคอนเทนเนอร์ Flex (Row, Column, Flex) Expanded ไม่มีรูปแบบภาพเป็นของตัวเอง — มันเพียงจัดการข้อจำกัด (constraints) ที่ส่งต่อไปยังองค์ประกอบลูก
หัวใจของ Expanded คือกลไก Flex ที่เฟรมเวิร์ก Flutter จัดเตรียมไว้ เมื่อ Row หรือ Column คำนวณขนาดของลูก พวกมันจะจัดสรรพื้นที่ให้กับองค์ประกอบที่ไม่ยืดหยุ่นก่อน (วิดเจ็ตทั่วไปที่มีขนาดคงที่) จากนั้นกระจายพื้นที่ที่เหลือระหว่างลูก Expanded และ Flexible ตามสัดส่วนของค่า flex
Expanded ใช้ Flexible.fit = FlexFit.tight ซึ่งหมายความว่าลูกของ Expanded ต้องครอบครองพื้นที่ที่จัดสรรทั้งหมด แม้ว่าขนาดของมันจะเล็กกว่า ต่างจาก Flexible ที่มี Fit.loose ซึ่งลูกสามารถเล็กกว่าพื้นที่ที่จัดสรรได้ Expanded จะบังคับขยายเนื้อหา
สรุป: Expanded เป็นเครื่องมือหลักสำหรับสร้างเลย์เอาต์ตามสัดส่วนใน Flutter ใช้เมื่อคุณต้องการให้องค์ประกอบเติมเต็มความกว้างหรือความสูงที่มีอยู่ทั้งหมดอย่างแน่นอน
Expanded และ Flexible ต่างก็กระจายพื้นที่ในคอนเทนเนอร์ Flex แต่ทำงานแตกต่างกันโดยพื้นฐาน ความแตกต่างอยู่ที่คุณสมบัติ fit ซึ่งกำหนดว่าลูกสามารถเล็กกว่าพื้นที่ที่มีอยู่ได้หรือไม่
Expanded มีโมเดลพฤติกรรมที่เข้มงวด: fit ของมันเท่ากับ FlexFit.tight ซึ่งหมายความว่าวิดเจ็ตลูกได้รับข้อจำกัดเท่ากับพื้นที่ที่มีอยู่ — ไม่มากไม่น้อย ถ้าลูกเล็กกว่ามันจะยืดออก ถ้าใหญ่กว่ามันจะหดตัว Flexible ใช้ FlexFit.loose ทำให้องค์ประกอบลูกสามารถมีขนาดใดก็ได้ภายในพื้นที่ที่จัดสรร
ในทางปฏิบัติ: ถ้า Row มี Expanded สองตัวที่มี flex=1 แต่ละตัวจะครอบครองครึ่งหนึ่งของความกว้างพอดี ถ้าคุณแทนที่ด้วย Flexible ที่มี fit.loose ลูกแต่ละตัวอาจเล็กกว่าครึ่งหนึ่งถ้าขนาดของมันเล็กกว่า — พื้นที่ที่เหลือจะว่างเปล่า
สรุป: ใช้ Expanded สำหรับเลย์เอาต์ตามสัดส่วนที่เข้มงวด Flexible เมื่อลูกสามารถเล็กกว่าพื้นที่ที่มีอยู่ได้ ถ้าไม่แน่ใจ — เริ่มด้วย Expanded มันให้พฤติกรรมที่คาดเดาได้มากกว่า
ค่า Flex (พารามิเตอร์ flex) คือค่าตัวเลขที่กำหนดสัดส่วนของพื้นที่ว่างที่ Expanded จะได้รับ โดยค่าเริ่มต้น flex=1 หมายถึงการกระจายเท่า ๆ กันระหว่างลูก Expanded ทั้งหมด
อัลกอริทึมการกระจายทำงานในสามขั้นตอน ขั้นแรก: Flutter คำนวณขนาดภายในของลูกที่ไม่ยืดหยุ่นทั้งหมด ขั้นที่สอง: พื้นที่ที่เหลือถูกหารด้วยผลรวมของค่า flex ทั้งหมด ขั้นที่สาม: แต่ละ Expanded ได้รับส่วนแบ่งเท่ากับค่า flex ของมันคูณด้วยขนาดของหนึ่งหน่วย flex
ตัวอย่างเช่น Row กว้าง 300px มี Expanded สองตัว: ตัวแรกมี flex=2 ตัวที่สองมี flex=1 พื้นที่ว่าง (300px ลบลูกที่ไม่ยืดหยุ่น) ถูกแบ่งเป็น 3 ส่วน ตัวแรกได้รับ 2/3 ตัวที่สองได้รับ 1/3 ถ้าไม่มีลูกที่ไม่ยืดหยุ่น ตัวแรกจะได้รับ 200px ตัวที่สองจะได้รับ 100px
ค่า flex สามารถเป็นจำนวนเต็มบวกใดก็ได้ ค่า 0 เป็นกรณีพิเศษ: Expanded ที่มี flex=0 ทำตัวเหมือนวิดเจ็ตที่ไม่ยืดหยุ่นทั่วไป ครอบครองพื้นที่ขั้นต่ำตามขนาดของลูก พฤติกรรมนี้เทียบเท่ากับการไม่มี Expanded
สรุป: ค่า flex เป็นกุญแจสำคัญในการสร้างเลย์เอาต์ที่ยืดหยุ่น ใช้อัตราส่วน 1:1 สำหรับคอลัมน์เท่ากัน 2:1 สำหรับแผงที่มีพื้นที่หลักและด้านข้าง 3:1 สำหรับอินเทอร์เฟซที่มีการนำทางแคบ
ตัวอย่างที่ 1 แสดงการใช้งานพื้นฐานของ Expanded ใน Row เพื่อสร้างสามคอลัมน์เท่ากัน
Row(
children: [
Expanded(
child: Container(
color: Colors.red,
),
),
Expanded(
child: Container(
color: Colors.green,
),
),
Expanded(
child: Container(
color: Colors.blue,
),
),
],
)
ในตัวอย่างนี้ Expanded สามตัวที่มี flex=1 (ค่าเริ่มต้น) แบ่งความกว้างของ Row เท่า ๆ กัน คอนเทนเนอร์ขยายไปจนถึงความสูงเต็มที่กำหนดโดย Row และครอบครองส่วนแบ่งเท่ากัน วิธีการนี้สะดวกสำหรับการสร้างเลย์เอาต์แบบคอลัมน์ที่มีการกระจายตามสัดส่วน
ตัวอย่างที่ 2 แสดงการใช้ค่า flex ที่แตกต่างกันเพื่อสร้างเลย์เอาต์ที่มีแถบด้านข้างและเนื้อหาหลัก
Row(
children: [
Expanded(
flex: 1,
child: Container(
color: Colors.grey.200,
child: const Center(
child: Text('แถบด้านข้าง'),
),
),
),
Expanded(
flex: 3,
child: Container(
color: Colors.white,
child: const Center(
child: Text('พื้นที่เนื้อหา'),
),
),
),
],
)
ตัวอย่างที่สองสร้างเลย์เอาต์ทั่วไปที่มีแถบด้านข้าง (25%) และพื้นที่เนื้อหาหลัก (75%) flex=1 และ flex=3 ให้อัตราส่วน 1:3 เมื่อความกว้างหน้าจอเปลี่ยนไป สัดส่วนจะถูกเก็บรักษาโดยอัตโนมัติ — นี่คือพื้นฐานของอินเทอร์เฟซที่ปรับเปลี่ยนได้
สรุป: Expanded ที่มีค่า flex ต่างกันเป็นเครื่องมือมาตรฐานสำหรับสร้างเลย์เอาต์ที่ปรับเปลี่ยนได้ การรวม Expanded ใน Column ช่วยให้สามารถสร้างการจัดวางตามสัดส่วนทั้งแนวนอนและแนวตั้ง
ข้อผิดพลาด 1: การใช้ Expanded นอก Row, Column หรือ Flex ถ้าคุณวาง Expanded โดยตรงใน Stack, ListView หรือคอนเทนเนอร์อื่นที่ไม่ใช่ Flex Flutter จะโยน LayoutException พร้อมข้อความ "Expanded widgets must be placed inside Flex widgets" วิธีแก้: ตรวจสอบวิดเจ็ตหลัก — เฉพาะ Row, Column หรือ Flex
ข้อผิดพลาด 2: การวาง Expanded ภายใน ListView โดยไม่ระบุ shrinkWrap โดยค่าเริ่มต้น ListView มีความสูงไม่สิ้นสุดในทิศทางการเลื่อน และ Expanded ไม่สามารถคำนวณส่วนแบ่งของมันได้ วิธีแก้: ใช้ shrinkWrap: true หรือห่อ ListView ใน SizedBox ที่มีความสูงคงที่
ข้อผิดพลาด 3: Expanded หลายตัวที่มีค่ารวม flex เกินพื้นที่ว่าง ถ้า Row ที่มีความกว้างจำกัดมี Expanded รวมถึงวิดเจ็ตที่มีขนาดภายในใหญ่ อาจเกิดการล้น วิธีแก้: ตรวจสอบขนาดขั้นต่ำของลูกที่ไม่ยืดหยุ่นและใช้ FittedBox หรือ Flex fit หากจำเป็น
ข้อผิดพลาด 4: Expanded ที่ซ้อนกันใน Column ภายใน Row ถ้า Expanded ภายใน Column มี Expanded อีกตัวภายใน Row อาจเกิดความขัดแย้งของข้อจำกัด วิธีแก้: จำกัดความลึกของการซ้อนหรือใช้ ConstrainedBox เพื่อกำหนดขนาดอย่างชัดเจนในระดับกลาง
สรุป: Expanded ต้องการบริบทหลักที่ถูกต้อง ตรวจสอบเสมอว่า Expanded ถูกวางโดยตรงใน Row, Column หรือ Flex และหลีกเลี่ยงการซ้อนกันโดยไม่มีขนาดที่ชัดเจน
คำถามที่พบบ่อย
SizedBox.expand บังคับขยายลูกไปยังขนาดที่กำหนดโดยข้อจำกัดภายนอก แต่ไม่มีส่วนร่วมในการกระจาย flex Expanded ทำงานเฉพาะภายในคอนเทนเนอร์ Flex และพิจารณาค่า flex ในการกระจายพื้นที่ว่างระหว่างลูก
ไม่ Stack ไม่ใช่คอนเทนเนอร์ Flex และการใช้ Expanded ภายในจะทำให้เกิด LayoutException สำหรับการขยายลูกใน Stack ให้ใช้ Positioned.fill หรือ BoxConstraints.expand
โดยค่าเริ่มต้น flex=1 Expanded ทั้งหมดที่ไม่มี flex ที่ชัดเจนจะได้รับส่วนแบ่งเท่ากันของพื้นที่ว่าง ถ้า Row มี Expanded สามตัวที่ไม่มี flex แต่ละตัวจะครอบครองหนึ่งในสามของพื้นที่ว่างพอดี
วาง Expanded ใน Row สำหรับการขยายแนวนอน สำหรับการขยายแนวตั้งใช้ Expanded ภายใน Column ถ้าต้องการจำกัดขนาด ให้ห่อ Expanded หรือลูกของมันใน SizedBox
Expanded ทำงานกับ Flex ซึ่งรวมถึง Row และ Column เป็นคลาสย่อย Wrap ไม่ใช่คอนเทนเนอร์ Flex และไม่รองรับ Expanded สำหรับการกระจายพื้นที่ใน Wrap ให้ใช้วิธีอื่น เช่น RunAlignment
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม