MediaQuery là một đối tượng trong Flutter cung cấp thông tin về môi trường phương tiện hiện tại: kích thước màn hình, hướng thiết bị, mật độ điểm ảnh, lề hệ thống và kích thước phông chữ. MediaQueryData là một vùng chứa cho tất cả các chỉ số này, có thể truy cập qua MediaQuery.of(context). Theo tài liệu chính thức của Flutter (2026), MediaQuery là nền tảng của thiết kế thích ứng: qua đó xác định hiển thị bố cục di động hay máy tính bảng, tính toán lề cho vùng an toàn và chọn kích thước phần tử tương ứng với màn hình.
Những điểm chính
MediaQuery là một widget và lớp trong Flutter cung cấp dữ liệu về môi trường phương tiện của ứng dụng. MediaQuery bao bọc toàn bộ ứng dụng trong widget gốc MaterialApp hoặc CupertinoApp và bất kỳ widget con nào cũng có thể truy cập dữ liệu này qua MediaQuery.of(context).
Khi Flutter khởi chạy một ứng dụng, nó tạo một thể hiện của MediaQueryData chứa tất cả các chỉ số của thiết bị hiện tại. Dữ liệu này tự động cập nhật khi có thay đổi: xoay thiết bị, thay đổi kích thước cửa sổ (trên máy tính để bàn), bàn phím xuất hiện hoặc thay đổi cài đặt trợ năng hệ thống. MediaQuery xây dựng lại cây con widget khi có bất kỳ thay đổi dữ liệu nào, cung cấp khả năng thích ứng giao diện phản ứng.
MediaQueryData bao gồm: size (kích thước màn hình), devicePixelRatio (mật độ điểm ảnh), textScaleFactor (tỷ lệ phông chữ từ cài đặt hệ thống), viewInsets (vùng bị bàn phím che phủ), viewPadding (lề hệ thống), orientation (hướng) và platformBrightness (chủ đề sáng hoặc tối).
Tóm lại: MediaQuery là nguồn thông tin trung tâm về thiết bị trong Flutter. Truy cập MediaQuery.of(context) là bước đầu tiên để xây dựng bất kỳ giao diện thích ứng nào.
MediaQueryData chứa hàng chục thuộc tính, nhưng những thuộc tính được sử dụng nhiều nhất là những thuộc tính ảnh hưởng đến việc xây dựng bố cục. Hãy xem các thuộc tính chính.
MediaQuery.of(context).size trả về một đối tượng Size với chiều rộng và chiều cao màn hình tính bằng pixel độc lập thiết bị (dip). Các giá trị này không tính đến lề hệ thống. Đối với tính toán bố cục thích ứng, size là chỉ số chính: nó xác định các điểm ngắt cho bố cục di động, máy tính bảng và máy tính để bàn.
ViewPadding là các lề mà hệ thống dành riêng cho thanh trạng thái, notch (phần cắt trên màn hình), bảng điều hướng hệ thống và chỉ báo trang chủ (trên iOS). Nếu không tính đến các lề này, nội dung có thể xuất hiện bên dưới các phần tử hệ thống. MediaQuery.of(context).padding trả về một EdgeInsets cần được áp dụng làm đệm cho vùng chứa gốc của trang.
ViewInsets là vùng màn hình bị bàn phím ảo che phủ. Đối với các trường nhập liệu, việc theo dõi viewInsets.bottom là rất quan trọng để nâng nội dung lên trên bàn phím. Flutter xử lý việc này tự động trong scaffold, nhưng đối với bố cục tùy chỉnh, bạn cần sử dụng trực tiếp MediaQuery.of(context).viewInsets.
Orientation — hướng dọc (portrait) hoặc ngang (landscape). Nó được xác định bằng cách so sánh chiều rộng và chiều cao: nếu chiều rộng nhỏ hơn chiều cao — portrait, ngược lại — landscape. Trong mã sản xuất, hướng được sử dụng để chuyển đổi giữa bố trí dọc và ngang của các phần tử.
Tóm lại: bốn thuộc tính chính — size, viewPadding, viewInsets và orientation — bao phủ 90% các tác vụ thiết kế thích ứng. Các thuộc tính còn lại (textScaleFactor, platformBrightness, devicePixelRatio) được sử dụng cho các tình huống cụ thể.
MediaQuery là nền tảng của thiết kế thích ứng trong Flutter. Qua đó xác định các điểm ngắt, chuyển đổi bố cục theo kích thước màn hình và điều chỉnh lề cho các thiết bị khác nhau.
Tình huống điển hình: một ứng dụng di động cần hiển thị danh sách sản phẩm. Trên điện thoại (chiều rộng < 600dp) — một cột. Trên máy tính bảng (chiều rộng 600–900dp) — hai cột. Trên máy tính để bàn (chiều rộng > 900dp) — ba cột. MediaQuery.of(context).size.width cho phép chọn động số lượng cột mà không cần màn hình riêng cho mỗi hệ số hình dạng.
Tình huống thứ hai: tính đến lề cử chỉ hệ thống trên các thiết bị hiện đại. Trên iPhone có Dynamic Island hoặc Android có điều hướng bằng cử chỉ, lề hệ thống tiêu tốn một phần màn hình. MediaQuery.of(context).padding trả về các giá trị chính xác cho từng loại thiết bị và Scaffold tự động áp dụng chúng qua body. Đối với widget tùy chỉnh, bạn cần truyền đệm từ MediaQuery một cách rõ ràng.
Tình huống thứ ba: thích ứng với cài đặt trợ năng hệ thống. MediaQuery.of(context).textScaleFactor cho biết người dùng đã tăng kích thước phông chữ trong cài đặt bao nhiêu. Ở textScaleFactor > 1.3, bố cục có thể bị hỏng — văn bản dài vượt quá giới hạn thẻ. Bố cục thích ứng nên tính đến điều này và nếu cần, chuyển sang bố cục đơn giản hơn.
Tóm lại: MediaQuery không chỉ là nguồn chỉ số mà còn là công cụ để xây dựng giao diện thực sự thích ứng. Sử dụng nó cho các điểm ngắt, vùng an toàn và các cân nhắc về trợ năng.
Ví dụ 1 minh họa cách lấy kích thước màn hình và áp dụng điểm ngắt để chọn số lượng cột.
int getColumnCount(BuildContext context) {
final width = MediaQuery.of(context).size.width;
if (width > 900) return 3;
if (width > 600) return 2;
return 1;
}
Ví dụ trên cho thấy một hàm chọn số lượng cột dựa trên chiều rộng màn hình. Các điểm ngắt 600 và 900 tương ứng với các tiêu chuẩn Material Design được chấp nhận rộng rãi cho điện thoại, máy tính bảng và máy tính để bàn.
Ví dụ 2 — sử dụng MediaQuery với viewPadding để đặt nội dung chính xác có tính đến lề hệ thống.
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(),
);
}
Trong ví dụ này, padding bao bọc nội dung trong Padding sử dụng lề hệ thống. top tính đến thanh trạng thái và notch, left/right các vùng an toàn. bottom không được bao gồm vì Scaffold thường tự xử lý điều hướng dưới cùng.
Ví dụ 3 — xác định hướng và thay đổi bố trí phần tử.
Widget build(BuildContext context) {
final isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
return isPortrait
? const Column(
children: [HeaderBanner(), ContentList()],
)
: const Row(
children: [HeaderBanner(), ContentList()],
);
}
Trong chế độ dọc, các phần tử được bố trí theo chiều dọc (Column); trong chế độ ngang, theo chiều ngang (Row). Cách tiếp cận này tận dụng không gian tốt nhất khi xoay thiết bị.
Tóm lại: MediaQuery là công cụ chính để xây dựng bố cục thích ứng. Luôn tính đến lề hệ thống, điểm ngắt và hướng khi phát triển giao diện Flutter.
Lỗi 1: gọi MediaQuery.of(context) bên ngoài ngữ cảnh nơi MediaQuery được thiết lập. Nếu một widget nằm trên MediaQuery trong cây, lệnh gọi sẽ gây ra lỗi thời gian chạy. Giải pháp: luôn gọi MediaQuery.of(context) bên trong các widget được bao bọc bởi MaterialApp hoặc CupertinoApp, nơi MediaQuery được thiết lập làm widget gốc.
Lỗi 2: quên vùng an toàn. Các nhà phát triển sử dụng MediaQuery.size để định vị phần tử mà không tính đến lề hệ thống. Trên các thiết bị có notch hoặc điều hướng bằng cử chỉ, nội dung bị đặt dưới thanh trạng thái. Giải pháp: trừ MediaQuery.of(context).padding khỏi tọa độ định vị.
Lỗi 3: gắn chặt với kích thước. Sử dụng MediaQuery.of(context).size.width để đặt kích thước chính xác của phần tử (width: size.width * 0.3) chỉ hoạt động trên các thiết bị có cùng hệ số hình dạng. Trên máy tính để bàn hoặc máy tính bảng, bố cục trông không tự nhiên. Giải pháp: sử dụng điểm ngắt kết hợp với Expanded và Flexible để có bố cục linh hoạt, không phải tỷ lệ phần trăm cố định.
Lỗi 4: bỏ qua textScaleFactor. Khi người dùng tăng phông chữ hệ thống, giao diện có thể bị hỏng — văn bản vượt quá giới hạn vùng chứa. Giải pháp: kiểm tra MediaQuery.of(context).textScaleFactor và ở giá trị trên 1.3, chuyển sang bố cục đơn giản hơn có cuộn.
Tóm lại: MediaQuery là một công cụ mạnh mẽ nhưng tinh tế. Hãy tính đến lề hệ thống, hướng và cài đặt trợ năng để đảm bảo giao diện hiển thị chính xác trên tất cả các thiết bị.
Câu hỏi thường gặp
MediaQuery.size là tổng kích thước màn hình hoặc cửa sổ ứng dụng tính bằng pixel logic. MediaQuery.viewInsets là vùng bị bàn phím hệ thống che phủ. Để tính không gian khả dụng không có bàn phím: size.height - viewInsets.bottom.
LayoutBuilder cung cấp kích thước của vùng chứa cha, không phải toàn bộ màn hình. Sử dụng LayoutBuilder khi kích thước widget phụ thuộc vào không gian khả dụng bên trong một cha cụ thể và MediaQuery khi bạn cần các chỉ số màn hình toàn cục.
Tự động. Khi xoay thiết bị, Flutter cập nhật MediaQueryData và xây dựng lại cây con. Thuộc tính orientation thay đổi và trình xây dựng của tất cả widget đã đăng ký được gọi với dữ liệu mới.
Có. Bằng cách bao bọc một phần widget trong MediaQuery với dữ liệu ghi đè qua MediaQuery.removePadding, MediaQuery.removeViewInsets hoặc MediaQuery với Data khác. Điều này được sử dụng để nhúng trong iframe hoặc chế độ xem trước.
Để kiểm thử, Flutter cung cấp setScreenSize và trình bao bọc MediaQuery trong môi trường kiểm thử. Đối với kiểm thử widget, hãy bao bọc thành phần đang kiểm thử trong MaterialApp hoặc MediaQuery với dữ liệu kiểm thử để kiểm soát kích thước màn hình.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm