MediaQuery คือออบเจ็กต์ใน Flutter ที่ให้ข้อมูลเกี่ยวกับสภาพแวดล้อมมีเดียปัจจุบัน: ขนาดหน้าจอ การวางแนวอุปกรณ์ ความหนาแน่นของพิกเซล ระยะขอบของระบบ และขนาดฟอนต์ MediaQueryData คือคอนเทนเนอร์สำหรับเมตริกทั้งหมดนี้ ซึ่งเข้าถึงได้ผ่าน MediaQuery.of(context) ตามเอกสารทางการของ Flutter (2026) MediaQuery คือพื้นฐานของการออกแบบแบบปรับเปลี่ยนได้: ผ่านมันจะกำหนดว่าจะแสดงเลย์เอาต์มือถือหรือแท็บเล็ต คำนวณระยะขอบสำหรับพื้นที่ปลอดภัย และเลือกขนาดองค์ประกอบสัมพันธ์กับหน้าจอ
ประเด็นสำคัญ
MediaQuery คือวิดเจ็ตและคลาสใน Flutter ที่ให้ข้อมูลเกี่ยวกับสภาพแวดล้อมมีเดียของแอปพลิเคชัน MediaQuery ห่อหุ้มทั้งแอปพลิเคชันในวิดเจ็ตรูท MaterialApp หรือ CupertinoApp และวิดเจ็ตลูกใด ๆ สามารถเข้าถึงข้อมูลนี้ผ่าน MediaQuery.of(context)
เมื่อ Flutter เริ่มต้นแอปพลิเคชัน มันจะสร้างอินสแตนซ์ของ MediaQueryData ที่มีเมตริกทั้งหมดของอุปกรณ์ปัจจุบัน ข้อมูลนี้จะอัปเดตโดยอัตโนมัติเมื่อมีการเปลี่ยนแปลง: การหมุนอุปกรณ์ การเปลี่ยนขนาดหน้าต่าง (บนเดสก์ท็อป) การปรากฏของแป้นพิมพ์ หรือการเปลี่ยนแปลงการตั้งค่าการเข้าถึงของระบบ MediaQuery สร้างแผนผังย่อยวิดเจ็ตใหม่เมื่อมีการเปลี่ยนแปลงข้อมูลใด ๆ ทำให้เกิดการปรับเปลี่ยนอินเทอร์เฟซแบบโต้ตอบ
MediaQueryData ประกอบด้วย: size (ขนาดหน้าจอ), devicePixelRatio (ความหนาแน่นของพิกเซล), textScaleFactor (สเกลฟอนต์จากการตั้งค่าระบบ), viewInsets (พื้นที่ที่ถูกแป้นพิมพ์ครอบคลุม), viewPadding (ระยะขอบของระบบ), orientation (การวางแนว) และ platformBrightness (ธีมสว่างหรือมืด)
สรุป: MediaQuery คือแหล่งข้อมูลกลางของอุปกรณ์ใน Flutter การเข้าถึง MediaQuery.of(context) คือขั้นตอนแรกในการสร้างอินเทอร์เฟซแบบปรับเปลี่ยนได้
MediaQueryData มีคุณสมบัติมากมาย แต่ที่ใช้บ่อยที่สุดคือคุณสมบัติที่ส่งผลต่อการสร้างเลย์เอาต์ มาดูคุณสมบัติหลักกัน
MediaQuery.of(context).size ส่งคืนออบเจ็กต์ Size ที่มีความกว้างและความสูงของหน้าจอในพิกเซลอิสระจากอุปกรณ์ (dip) ค่าเหล่านี้ไม่คำนึงถึงระยะขอบของระบบ สำหรับการคำนวณเลย์เอาต์แบบปรับเปลี่ยนได้ size คือเมตริกหลัก: มันกำหนดจุดแบ่งสำหรับเลย์เอาต์มือถือ แท็บเล็ต และเดสก์ท็อป
ViewPadding คือระยะขอบที่ระบบสงวนไว้สำหรับแถบสถานะ รอยบาก (รอยตัดบนหน้าจอ) แผงนำทางระบบ และตัวบ่งชี้หน้าหลัก (บน iOS) หากไม่คำนึงถึงระยะขอบเหล่านี้ เนื้อหาอาจปรากฏใต้ส่วนประกอบของระบบ MediaQuery.of(context).padding ส่งคืน EdgeInsets ที่ควรใช้เป็น padding กับคอนเทนเนอร์รูทของหน้า
ViewInsets คือพื้นที่หน้าจอที่ถูกแป้นพิมพ์ซอฟต์แวร์ครอบคลุม สำหรับฟิลด์ป้อนข้อมูล การติดตาม viewInsets.bottom เป็นสิ่งสำคัญในการยกเนื้อหาขึ้นเหนือแป้นพิมพ์ Flutter จัดการสิ่งนี้โดยอัตโนมัติใน scaffold แต่สำหรับเลย์เอาต์แบบกำหนดเอง คุณต้องใช้ MediaQuery.of(context).viewInsets โดยตรง
Orientation — การวางแนวแนวตั้ง (portrait) หรือแนวนอน (landscape) ถูกกำหนดโดยการเปรียบเทียบความกว้างและความสูง: หากความกว้างน้อยกว่าความสูง — แนวตั้ง มิฉะนั้น — แนวนอน ในโค้ดการผลิต การวางแนวถูกใช้เพื่อสลับระหว่างการจัดเรียงแนวตั้งและแนวนอนขององค์ประกอบ
สรุป: สี่คุณสมบัติหลัก — size, viewPadding, viewInsets และ orientation — ครอบคลุม 90% ของงานออกแบบแบบปรับเปลี่ยนได้ คุณสมบัติที่เหลือ (textScaleFactor, platformBrightness, devicePixelRatio) ใช้สำหรับสถานการณ์เฉพาะ
MediaQuery คือพื้นฐานของการออกแบบแบบปรับเปลี่ยนได้ใน Flutter ผ่านมันกำหนดจุดแบ่ง สลับเลย์เอาต์ตามขนาดหน้าจอ และปรับระยะขอบสำหรับอุปกรณ์ต่าง ๆ
สถานการณ์ทั่วไป: แอปมือถือต้องแสดงรายการสินค้า บนโทรศัพท์ (ความกว้าง < 600dp) — หนึ่งคอลัมน์ บนแท็บเล็ต (ความกว้าง 600–900dp) — สองคอลัมน์ บนเดสก์ท็อป (ความกว้าง > 900dp) — สามคอลัมน์ MediaQuery.of(context).size.width ช่วยให้เลือกจำนวนคอลัมน์แบบไดนามิกโดยไม่ต้องมีหน้าจอแยกสำหรับแต่ละฟอร์มแฟคเตอร์
สถานการณ์ที่สอง: การคำนึงถึงระยะขอบท่าทางของระบบบนอุปกรณ์สมัยใหม่ บน iPhone ที่มี Dynamic Island หรือ Android ที่มีการนำทางด้วยท่าทาง ระยะขอบของระบบจะกินพื้นที่ส่วนหนึ่งของหน้าจอ MediaQuery.of(context).padding ส่งคืนค่าที่ถูกต้องสำหรับอุปกรณ์แต่ละประเภท และ Scaffold จะนำไปใช้โดยอัตโนมัติผ่าน body สำหรับวิดเจ็ตแบบกำหนดเอง คุณต้องส่ง padding จาก MediaQuery อย่างชัดเจน
สถานการณ์ที่สาม: การปรับตัวตามการตั้งค่าการเข้าถึงของระบบ MediaQuery.of(context).textScaleFactor แสดงให้เห็นว่าผู้ใช้เพิ่มขนาดฟอนต์ในการตั้งค่ามากเพียงใด ที่ textScaleFactor > 1.3 เลย์เอาต์อาจเสีย — ข้อความยาวเกินขอบเขตการ์ด เลย์เอาต์แบบปรับเปลี่ยนได้ควรคำนึงถึงสิ่งนี้ และหากจำเป็น ให้สลับไปใช้เลย์เอาต์ที่ง่ายกว่า
สรุป: MediaQuery ไม่ใช่แค่แหล่งที่มาของเมตริก แต่เป็นเครื่องมือสำหรับสร้างอินเทอร์เฟซที่ปรับเปลี่ยนได้อย่างแท้จริง ใช้มันสำหรับจุดแบ่ง พื้นที่ปลอดภัย และข้อพิจารณาด้านการเข้าถึง
ตัวอย่างที่ 1 สาธิตการรับขนาดหน้าจอและการใช้จุดแบ่งเพื่อเลือกจำนวนคอลัมน์
int getColumnCount(BuildContext context) {
final width = MediaQuery.of(context).size.width;
if (width > 900) return 3;
if (width > 600) return 2;
return 1;
}
ตัวอย่างด้านบนแสดงฟังก์ชันสำหรับเลือกจำนวนคอลัมน์ตามความกว้างหน้าจอ จุดแบ่ง 600 และ 900 สอดคล้องกับมาตรฐาน Material Design ที่เป็นที่ยอมรับโดยทั่วไปสำหรับโทรศัพท์ แท็บเล็ต และเดสก์ท็อป
ตัวอย่างที่ 2 — การใช้ MediaQuery กับ viewPadding สำหรับการวางตำแหน่งเนื้อหาที่ถูกต้องโดยคำนึงถึงระยะขอบของระบบ
Widget build(BuildContext context) {
final padding = MediaQuery.of(context).padding;
return Padding(
padding: EdgeInsets.only(
top: padding.top,
left: padding.left,
right: padding.right,
),
child: const MyContent(),
);
}
ในตัวอย่างนี้ padding ห่อหุ้มเนื้อหาใน Padding โดยใช้ระยะขอบของระบบ top คำนึงถึงแถบสถานะและรอยบาก left/right พื้นที่ปลอดภัย bottom ไม่รวมเพราะ Scaffold มักจะจัดการนำทางด้านล่างเอง
ตัวอย่างที่ 3 — การกำหนดการวางแนวและการเปลี่ยนการจัดเรียงองค์ประกอบ
Widget build(BuildContext context) {
final isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
return isPortrait
? const Column(
children: [HeaderBanner(), ContentList()],
)
: const Row(
children: [HeaderBanner(), ContentList()],
);
}
ในโหมดแนวตั้ง องค์ประกอบถูกจัดเรียงแนวตั้ง (Column); ในโหมดแนวนอน จัดเรียงแนวนอน (Row) วิธีการนี้ใช้พื้นที่ให้เกิดประโยชน์สูงสุดเมื่อหมุนอุปกรณ์
สรุป: MediaQuery คือเครื่องมือหลักสำหรับสร้างเลย์เอาต์แบบปรับเปลี่ยนได้ คำนึงถึงระยะขอบของระบบ จุดแบ่ง และการวางแนวเสมอเมื่อพัฒนาอินเทอร์เฟซ Flutter
ข้อผิดพลาด 1: การเรียก MediaQuery.of(context) นอกบริบทที่ตั้งค่า MediaQuery ไว้วิดเจ็ตอยู่เหนือ MediaQuery ในแผนผัง การเรียกจะทำให้เกิดข้อผิดพลาดรันไทม์ วิธีแก้ปัญหา: เรียก MediaQuery.of(context) ภายในวิดเจ็ตที่ห่อด้วย MaterialApp หรือ CupertinoApp ซึ่ง MediaQuery ถูกตั้งเป็นวิดเจ็ตรูทเสมอ
ข้อผิดพลาด 2: การลืม พื้นที่ปลอดภัย นักพัฒนาใช้ MediaQuery.size เพื่อวางตำแหน่งองค์ประกอบโดยไม่คำนึงถึงระยะขอบของระบบ บนอุปกรณ์ที่มีรอยบากหรือการนำทางด้วยท่าทาง เนื้อหาจะอยู่ใต้แถบสถานะ วิธีแก้ปัญหา: ลบ MediaQuery.of(context).padding จากพิกัดตำแหน่ง
ข้อผิดพลาด 3: การยึดติดกับขนาดอย่างตายตัว การใช้ MediaQuery.of(context).size.width เพื่อกำหนดขนาดที่แน่นอนขององค์ประกอบ (width: size.width * 0.3) ทำงานได้เฉพาะบนอุปกรณ์ที่มีฟอร์มแฟคเตอร์เดียวกัน บนเดสก์ท็อปหรือแท็บเล็ต เลย์เอาต์ดูไม่เป็นธรรมชาติ วิธีแก้ปัญหา: ใช้จุดแบ่งร่วมกับ Expanded และ Flexible สำหรับเลย์เอาต์ที่ยืดหยุ่น ไม่ใช่เปอร์เซ็นต์ตายตัว
ข้อผิดพลาด 4: การละเลย textScaleFactor เมื่อผู้ใช้เพิ่มฟอนต์ระบบ อินเทอร์เฟซอาจเสีย — ข้อความเกินขอบเขตคอนเทนเนอร์ วิธีแก้ปัญหา: ตรวจสอบ MediaQuery.of(context).textScaleFactor และที่ค่าสูงกว่า 1.3 ให้สลับไปใช้เลย์เอาต์ที่ง่ายกว่าพร้อมการเลื่อน
สรุป: MediaQuery เป็นเครื่องมือที่ทรงพลังแต่ละเอียดอ่อน คำนึงถึงระยะขอบของระบบ การวางแนว และการตั้งค่าการเข้าถึงเพื่อให้อินเทอร์เฟซแสดงผลถูกต้องบนทุกอุปกรณ์
คำถามที่พบบ่อย
MediaQuery.size คือขนาดทั้งหมดของหน้าจอหรือหน้าต่างแอปพลิเคชันในพิกเซลเชิงตรรกะ MediaQuery.viewInsets คือพื้นที่ที่ถูกแป้นพิมพ์ระบบครอบคลุม ในการคำนวณพื้นที่ว่างที่ไม่มีแป้นพิมพ์: size.height - viewInsets.bottom
LayoutBuilder ให้ขนาดของคอนเทนเนอร์หลัก ไม่ใช่ทั้งหน้าจอ ใช้ LayoutBuilder เมื่อขนาดวิดเจ็ตขึ้นอยู่กับพื้นที่ว่างภายในหลักเฉพาะ และใช้ MediaQuery เมื่อต้องการเมตริกหน้าจอโดยรวม
โดยอัตโนมัติ เมื่อหมุนอุปกรณ์ Flutter อัปเดต MediaQueryData และสร้างแผนผังย่อยใหม่ คุณสมบัติ orientation เปลี่ยนแปลงและ builder ของวิดเจ็ตที่สมัครรับข้อมูลทั้งหมดถูกเรียกด้วยข้อมูลใหม่
ได้ โดยการห่อส่วนของวิดเจ็ตใน MediaQuery ด้วยข้อมูลที่ถูกแทนที่ผ่าน MediaQuery.removePadding, MediaQuery.removeViewInsets หรือ MediaQuery ที่มี Data อื่น ซึ่งใช้สำหรับการฝังใน iframe หรือโหมดแสดงตัวอย่าง
สำหรับการทดสอบ Flutter มี setScreenSize และตัวห่อ MediaQuery ในสภาพแวดล้อมการทดสอบ สำหรับการทดสอบวิดเจ็ต ให้ห่อคอมโพเนนต์ที่กำลังทดสอบใน MaterialApp หรือ MediaQuery พร้อมข้อมูลทดสอบเพื่อควบคุมขนาดหน้าจอ
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ