Scaffold เป็นวิดเจ็ตโครงสร้างกลางใน Flutter ที่ใช้โครงสร้างหน้าจอ Material Design พื้นฐานกับ AppBar, Drawer, BottomNavigationBar และ FloatingActionButton มันไม่เพียงแค่วางตำแหน่งองค์ประกอบ แต่ยังให้สถาปัตยกรรมสำเร็จรูปพร้อมลำดับ z ที่ถูกต้องและการจัดการท่าทางของผู้ใช้ ตาม เอกสาร Flutter (2026) Scaffold เป็นองค์ประกอบรากที่จำเป็นสำหรับการทำงานที่ถูกต้องของคอมโพเนนต์ Material รวมถึง SnackBar และ BottomSheet ไม่เหมือนกับ Container หรือ Column Scaffold จัดการ SafeArea พื้นหลังแบบปรับได้และพฤติกรรมของแป้นพิมพ์โดยอัตโนมัติ ทำให้เป็นมาตรฐานสำหรับการสร้างหน้าจอในแอปพลิเคชันมือถือ
ประเด็นสำคัญ
Scaffold เป็นวิดเจ็ตเค้าโครงจากไลบรารี Material Design ที่สร้างโครงสร้างภาพพื้นฐานของหน้าจอ มันใช้รูปแบบแอปพลิเคชัน Material มาตรฐาน: แถบด้านบน, เนื้อหาหน้าจอ, เมนูด้านข้างและปุ่มลอย ไม่เหมือนกับ Container ที่กำหนดขนาดและสไตล์เท่านั้น Scaffold จัดการทั้งหน้าจอเป็นระบบรวม
ทุกแอปพลิเคชัน Flutter ที่สร้างด้วย Material Design เริ่มต้นด้วย MaterialApp ซึ่งภายในแต่ละหน้าจอจะถูกห่อหุ้มใน Scaffold Scaffold เป็นตัวที่รับประกันการแสดงผล AppBar ที่ถูกต้องบนทุกอุปกรณ์ โดยคำนึงถึง SafeArea สำหรับ iPhone X ขึ้นไป นอกจากนี้ยังรับผิดชอบลำดับ z: Drawer แสดงเหนือ body และ SnackBar แสดงเหนืออินเทอร์เฟซทั้งหมด แต่ใต้หน้าต่างโต้ตอบ
ตาม เอกสารอ้างอิง API Flutter (2026) Scaffold เป็นข้อกำหนดบังคับสำหรับการทำงานที่ถูกต้องของวิดเจ็ตเช่น SnackBar, BottomSheet และ PersistentBottomSheet หากไม่มี Scaffold คอมโพเนนต์เหล่านี้จะโยนข้อยกเว้นเนื่องจากต้องพึ่งพา InheritedWidget Scaffold.of เพื่อเข้าถึงบริบทของ Scaffold ดังนั้นการวางเนื้อหาใดๆ โดยตรงใน Container แทน Scaffold เป็นข้อผิดพลาดทั่วไปของผู้พัฒนามือใหม่ ซึ่งนำไปสู่การสูญเสียฟังก์ชันการทำงานของ Material
ในแอปพลิเคชัน Flutter ทั่วไป Scaffold อยู่ภายใน MaterialApp โดยปกติจะอยู่ภายใต้ WidgetsApp หรือ CupertinoApp ในการพัฒนาข้ามแพลตฟอร์ม MaterialApp สร้าง Navigator และธีม ในขณะที่ Scaffold กำหนดโครงสร้างของหน้าจอปัจจุบัน แต่ละหน้าจอสามารถมี Scaffold ของตัวเองกับ AppBar, Drawer และ BottomNavigationBar ที่ไม่ซ้ำกัน ซึ่งช่วยให้ปรับแต่งอินเทอร์เฟซได้อย่างยืดหยุ่นสำหรับหน้าเฉพาะ
สำหรับการปรับแต่งเชิงลึก Scaffold สามารถรวมกับ NestedScrollView — ซึ่งช่วยให้ใช้เอฟเฟกต์การเลื่อนที่ซับซ้อน เช่น AppBar ที่ยุบได้พร้อมเอฟเฟกต์พารัลแลกซ์ อย่างไรก็ตาม ในกรณีส่วนใหญ่ Scaffold มาตรฐานกับคุณสมบัติของมันก็เพียงพอสำหรับการสร้างหน้าจอที่พร้อมใช้งานจริง
Scaffold ประกอบด้วยโซนบังคับและไม่บังคับหลายโซน แต่ละโซนรับผิดชอบส่วนเฉพาะของอินเทอร์เฟซ มาดูแต่ละส่วนทีละส่วนเพื่อเข้าใจว่าพวกมันมีปฏิสัมพันธ์กันอย่างไร
AppBar คือแถบด้านบนของหน้าจอที่แสดงชื่อ ปุ่มนำทางและการกระทำ มันได้รับความสูงที่ถูกต้อง 56dp โดยอัตโนมัติและคำนึงถึง SafeArea สำหรับอุปกรณ์ที่มีรอยบาก TabBar สามารถฝังใน AppBar เพื่อสลับแท็บโดยใช้คุณสมบัติ bottom
Drawer คือแผงที่เลื่อนออกมาจากด้านซ้ายและให้การนำทางผ่านส่วนต่างๆ ของแอปพลิเคชัน Scaffold จะเพิ่มไอคอนแฮมเบอร์เกอร์ใน AppBar โดยอัตโนมัติหากตั้งค่าคุณสมบัติ drawer Drawer สามารถประกอบด้วย DrawerHeader, ListView พร้อมรายการเมนูและข้อมูลผู้ใช้
BottomNavigationBar คือแผงที่ด้านล่างของหน้าจอสำหรับสลับระหว่างส่วนหลัก ประกอบด้วยไอคอน 2 ถึง 5 ไอคอนพร้อมป้ายกำกับและรองรับ Material 3 พร้อมการแสดงสถานะที่ใช้งานผ่าน NavigationBar Scaffold วางไว้ที่ด้านล่างของหน้าจอ เลื่อน body ขึ้นโดยอัตโนมัติเพื่อไม่ให้เนื้อหาถูกบดบัง
FloatingActionButton คือปุ่มกลมที่วางไว้ที่มุมล่างขวาของหน้าจอ ใช้สำหรับการกระทำหลักบนหน้าจอ เช่น การเพิ่มรายการใหม่หรือส่งข้อความ Scaffold รองรับ FAB หลายตัวพร้อมแอนิเมชันแบบขยายผ่านคุณสมบัติ extended
Body คือพื้นที่กลางของหน้าจอที่วางเนื้อหาหลัก วิดเจ็ตใดๆ สามารถทำหน้าที่เป็น body: Column, ListView, GridView, Stack หรือการประกอบแบบกำหนดเอง Scaffold คำนวณความสูงของ body โดยอัตโนมัติโดยคำนึงถึง AppBar, BottomNavigationBar และ SafeArea ซึ่งช่วยลดความจำเป็นในการปรับขนาดด้วยตนเอง
Scaffold มีคุณสมบัติมากกว่า 30 รายการสำหรับปรับแต่งลักษณะและการทำงานของหน้าจอ รวมถึงทั้งคุณสมบัติบังคับ (body) และไม่บังคับที่ควบคุมระยะขอบ พื้นหลังและสถานะแป้นพิมพ์ การเข้าใจแต่ละคุณสมบัติช่วยกำหนดค่าอินเทอร์เฟซได้อย่างแม่นยำตามข้อกำหนดการออกแบบ
| คุณสมบัติ | ชนิด | คำอธิบาย |
|---|---|---|
| appBar | PreferredSizeWidget? | แถบด้านบนของหน้าจอพร้อมชื่อและการกระทำ |
| body | Widget? | เนื้อหาหลักของหน้าจอระหว่าง AppBar และ BottomNavigationBar |
| drawer | Widget? | แผงด้านข้างที่เปิดโดยการปัดจากด้านซ้าย |
| bottomNavigationBar | Widget? | แถบนำทางด้านล่าง (BottomNavigationBar หรือ NavigationBar) |
| floatingActionButton | Widget? | ปุ่มการกระทำแบบลอย |
| backgroundColor | Color? | สีพื้นหลังของ Scaffold ที่แทนที่ธีม |
| resizeToAvoidBottomInset | bool | การหด body อัตโนมัติเมื่อแป้นพิมพ์ปรากฏ |
คุณสมบัติ resizeToAvoidBottomInset สำคัญโดยเฉพาะเมื่อทำงานกับฟอร์ม: เมื่อตั้งค่าเป็น true (ค่าเริ่มต้น) Scaffold จะหด body โดยอัตโนมัติเมื่อแป้นพิมพ์ปรากฏ เพื่อให้ช่องป้อนข้อมูลมองเห็นได้ ซึ่งช่วยลดความจำเป็นในการเขียนตัวฟังแป้นพิมพ์แบบกำหนดเอง สำหรับสถานการณ์แบบกำหนดเองกับ SingleChildScrollView สามารถปิดใช้งานคุณสมบัตินี้ได้
มาดูตัวอย่างการใช้งานจริงของ Scaffold พร้อมชุดคอมโพเนนต์ Material ที่สมบูรณ์ โค้ดสร้างหน้าจอด้วย AppBar, Drawer, BottomNavigationBar, FloatingActionButton และ SnackBar — โครงสร้างแอปพลิเคชันมือถือทั่วไปใน Flutter
class MainScreen extends StatefulWidget {
const MainScreen({super.key});
@override
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
int selectedIndex = 0;
final List<Widget> pages = [
const HomePage(),
const SearchPage(),
const ProfilePage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('แอปของฉัน'),
actions: [
IconButton(icon: const Icon(Icons.search), onPressed: () {}),
],
),
body: pages[selectedIndex],
drawer: Drawer(
child: ListView(
children: [
const DrawerHeader(child: Text('เมนู')),
ListTile(title: const Text('การตั้งค่า'), onTap: () {}),
],
),
),
bottomNavigationBar: NavigationBar(
selectedIndex: selectedIndex,
onDestinationSelected: (int index) {
setState(() => selectedIndex = index);
},
destinations: const [
NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
NavigationDestination(icon: Icon(Icons.search), label: 'Search'),
NavigationDestination(icon: Icon(Icons.person), label: 'Profile'),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('ดำเนินการเสร็จสิ้น')),
);
},
child: const Icon(Icons.add),
),
);
}
}
ตัวอย่างใช้ NavigationBar จาก Material 3 แทน BottomNavigationBar ที่เลิกใช้แล้ว Scaffold เชื่อมโยงทุกส่วนโดยอัตโนมัติ: เมื่อเปิด Drawer SnackBar จะซ่อน; เมื่อสลับแท็บ body จะอัปเดต; และ FloatingActionButton ยังคงอยู่ที่เดิม ScaffoldMessenger รับประกันการแสดง SnackBar แม้จะมี Scaffold หลายตัวในลำดับชั้น
Material 3 (M3) คือวิวัฒนาการของ Material Design ที่ Google นำเสนอในปี 2023 Scaffold ใน M3 ได้รับการเปลี่ยนแปลงหลายอย่าง: วิดเจ็ต NavigationBar ใหม่แทน BottomNavigationBar, การรองรับสีแบบไดนามิกผ่าน ColorScheme.fromSeed และคำแนะนำที่อัปเดตสำหรับระยะขอบและความสูงของคอมโพเนนต์ การเปลี่ยนไปใช้ M3 ไม่ต้องการการเปลี่ยน Scaffold — เพียงแค่อัปเดตธีมของแอปพลิเคชัน
เพื่อเปิดใช้งาน Material 3 ในโปรเจกต์ จำเป็นต้องตั้งค่า useMaterial3: true ใน ThemeData Scaffold จะปรับสไตล์ภาพโดยอัตโนมัติ: ระยะขอบใหญ่ขึ้น (24dp แทน 16dp), สีถูกคำนวณใหม่จากสีเริ่มต้น และ FloatingActionButton ได้ขนาดใหญ่ขึ้นพร้อมมุมโค้ง ในขณะเดียวกัน คุณสมบัติ Scaffold ที่มีอยู่ทั้งหมดยังคงทำงานได้
ตาม ข้อกำหนด Material Design 3 (2026) แนะนำให้ใช้ NavigationBar กับสามถึงห้ารายการแทน BottomNavigationBar Scaffold รองรับทั้งสองตัวเลือก แต่ NavigationBar ให้การรองรับที่ดีกว่าสำหรับการปรับเปลี่ยนและ Material You บนอุปกรณ์ Pixel
สำหรับการทำงานที่ถูกต้องของ Scaffold กับ M3 เพียงแค่อัปเดตธีมและแทนที่ BottomNavigationBar ด้วย NavigationBar สีจะถูกคำนวณโดยอัตโนมัติผ่าน ColorScheme.fromSeed และ Scaffold จะปรับระยะขอบตามมาตรฐานใหม่ หากจำเป็น สามารถแทนที่ backgroundColor ได้โดยตรง
คำถามที่พบบ่อย
Scaffold คือวิดเจ็ตโครงสร้างสำหรับทั้งหน้าจอพร้อมรองรับคอมโพเนนต์ Material (AppBar, Drawer, SnackBar) ในขณะที่ Container คือภาชนะพื้นฐานสำหรับองค์ประกอบย่อยเดียวโดยไม่มีการจัดการโครงสร้างหน้าจอ Scaffold ให้ลำดับ z, SafeArea และการจัดการท่าทางอัตโนมัติ ในขณะที่ Container กำหนดเฉพาะขนาดและสไตล์
ในทางเทคนิคได้ แต่ในทางปฏิบัติไม่แนะนำ หากคุณซ้อน Scaffold หนึ่งไว้ภายในอีกอันหนึ่ง Scaffold ด้านในจะสร้าง AppBar และ BottomNavigationBar ของตัวเอง ทำให้แผงซ้ำซ้อนและสับสนในลำดับ z สำหรับเค้าโครงที่ซับซ้อน ให้ใช้ NestedScrollView หรือ Column ภายใน body ของ Scaffold เดียว
SnackBar เป็นคอมโพเนนต์ย่อยของ Scaffold และต้องการการมีอยู่ของมันในแผนผังวิดเจ็ตเพื่อการแสดงผลที่ถูกต้อง Scaffold ให้ ScaffoldState ซึ่ง SnackBar ใช้เพื่อเคลื่อนไหวการปรากฏและวางตำแหน่งที่ด้านล่างของหน้าจอ หากไม่มี Scaffold SnackBar จะโยนข้อยกเว้นเนื่องจากไม่สามารถหา ScaffoldState ในบริบทผ่าน InheritedWidget
สีพื้นหลังของ Scaffold กำหนดผ่านคุณสมบัติ backgroundColor ซึ่งแทนที่สีธีมสำหรับหน้าจอเฉพาะ หากต้องการเปลี่ยนพื้นหลังแบบทั่วโลก ให้ตั้งค่า scaffoldBackgroundColor ใน ThemeData Material 3 คำนวณสีพื้นหลังจาก ColorScheme.surface โดยอัตโนมัติ แต่สามารถแทนที่ด้วยตนเองได้
ScaffoldMessenger คือยูทิลิตี้ที่นำมาใช้ใน Flutter 2.5 ซึ่งช่วยให้แสดง SnackBar และ BottomSheet โดยอิสระจาก Scaffold ปัจจุบันในลำดับชั้น ไม่เหมือนกับ Scaffold.of(context) ที่เลิกใช้แล้ว ScaffoldMessenger ทำงานได้อย่างถูกต้องเมื่อนำทางระหว่างหน้าจอและไม่สูญเสียบริบทระหว่างแอนิเมชัน แนะนำให้ใช้ ScaffoldMessenger เสมอสำหรับการตอบกลับผู้ใช้
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม