MediaQuery — obiekt we Flutter, dostarczający informacji o bieżącym środowisku medialnym: rozmiarze ekranu, orientacji urządzenia, gęstości pikseli, systemowych odstępach i rozmiarze czcionki. MediaQueryData — kontener dla wszystkich tych metryk, dostępny przez MediaQuery.of(context). Według oficjalnej dokumentacji Flutter (2026), MediaQuery to podstawa adaptacyjnego projektowania: za jego pomocą określa się, czy wyświetlać układ mobilny czy tabletowy, obliczać odstępy dla safe area i wybierać rozmiary elementów względem ekranu.
Najważniejsze
MediaQuery — to widget i klasa Flutter, która dostarcza dane o środowisku medialnym aplikacji. MediaQuery otacza całą aplikację w korzennym widgetcie MaterialApp lub CupertinoApp, a każdy widget potomny może uzyskać dostęp do tych danych przez MediaQuery.of(context).
Kiedy Flutter uruchamia aplikację, tworzy instancję MediaQueryData zawierającą wszystkie metryki bieżącego urządzenia. Dane te są aktualizowane automatycznie przy zmianach: obrocie urządzenia, zmianie rozmiaru okna (na desktopie), pojawieniu się klawiatury lub zmianie systemowych ustawień dostępności. MediaQuery przebudowuje poddrzewo widgetów przy każdej zmianie danych, zapewniając reaktywną adaptację interfejsu.
MediaQueryData obejmuje: size (rozmiar ekranu), devicePixelRatio (gęstość pikseli), textScaleFactor (skala czcionki z ustawień systemowych), viewInsets (obszar przykryty klawiaturą), viewPadding (systemowe odstępy), orientation (orientacja) i platformBrightness (jasny lub ciemny motyw).
Podsumowanie: MediaQuery — centralne źródło informacji o urządzeniu we Flutter. Dostęp do MediaQuery.of(context) to pierwszy krok w budowaniu każdego adaptacyjnego interfejsu.
MediaQueryData zawiera dziesiątki właściwości, ale najczęściej używane są te, które wpływają na budowanie układu. Omówmy kluczowe z nich.
MediaQuery.of(context).size zwraca obiekt Size z szerokością i wysokością ekranu w logicznych pikselach (device-independent pixels, dip). Te wartości nie uwzględniają systemowych odstępów. Do obliczeń adaptacyjnych układów size — główna metryka: na jej podstawie określa się breakpoints dla układu mobilnego, tabletowego i desktopowego.
ViewPadding — odstępy, które system rezerwuje dla paska stanu, notch (wycięcia na ekranie), systemowego panelu nawigacyjnego i wskaźnika domu (na iOS). Bez uwzględnienia tych odstępów zawartość może znaleźć się pod elementami systemowymi. MediaQuery.of(context).padding zwraca EdgeInsets, który należy zastosować jako padding do korzennego kontenera strony.
ViewInsets — obszar ekranu przykryty programową klawiaturą. Dla pól wprowadzania krytyczne jest śledzenie viewInsets.bottom, aby podnosić zawartość nad klawiaturą. Flutter automatycznie obsługuje to w scaffold, ale dla niestandardowych układów należy używać MediaQuery.of(context).viewInsets bezpośrednio.
Orientation — orientacja pionowa (portrait) lub pozioma (landscape). Określa się ją przez porównanie szerokości i wysokości: jeśli szerokość jest mniejsza niż wysokość — portrait, w przeciwnym razie — landscape. W kodzie produkcyjnym orientacji używa się do przełączania między pionowym a poziomym układem elementów.
Podsumowanie: cztery kluczowe właściwości — size, viewPadding, viewInsets i orientation — pokrywają 90% zadań adaptacyjnego projektowania. Pozostałe właściwości (textScaleFactor, platformBrightness, devicePixelRatio) są używane w specyficznych scenariuszach.
MediaQuery — podstawa adaptacyjnego projektowania we Flutter. Za jego pomocą określa się breakpoints, przełącza layout w zależności od rozmiaru ekranu i koryguje odstępy dla różnych urządzeń.
Typowy scenariusz: aplikacja mobilna powinna wyświetlać listę produktów. Na telefonie (szerokość < 600dp) — jedna kolumna. Na tablecie (szerokość 600–900dp) — dwie kolumny. Na desktopie (szerokość > 900dp) — trzy kolumny. MediaQuery.of(context).size.width pozwala dynamicznie wybierać liczbę kolumn bez osobnego ekranu dla każdego form factora.
Drugi scenariusz: uwzględnienie system gesture insets na nowoczesnych urządzeniach. Na iPhone z Dynamic Island lub Android z gesture navigation systemowe odstępy zabierają część ekranu. MediaQuery.of(context).padding zwraca poprawne wartości dla każdego typu urządzenia, a Scaffold automatycznie stosuje je przez body. Dla niestandardowych widgetów należy jawnie przekazywać padding z MediaQuery.
Trzeci scenariusz: adaptacja do systemowych ustawień dostępności. MediaQuery.of(context).textScaleFactor pokazuje, jak bardzo użytkownik zwiększył czcionkę w ustawieniach. Przy textScaleFactor > 1.3 układ może się zepsuć — długie teksty wychodzą poza granice kart. Adaptacyjne układy powinny to uwzględniać i, w razie potrzeby, przełączać się na prostszy układ.
Podsumowanie: MediaQuery — nie tylko źródło metryk, ale narzędzie do budowania prawdziwie adaptacyjnych interfejsów. Używaj go do breakpoints, safe area i uwzględniania dostępności.
Przykład 1 demonstruje pobieranie rozmiaru ekranu i zastosowanie breakpoints do wyboru liczby kolumn.
int getColumnCount(BuildContext context) {
final width = MediaQuery.of(context).size.width;
if (width > 900) return 3;
if (width > 600) return 2;
return 1;
}
Przykład powyżej pokazuje funkcję wyboru liczby kolumn na podstawie szerokości ekranu. Breakpoints 600 i 900 odpowiadają powszechnie przyjętym standardom Material Design dla telefonów, tabletów i desktopu.
Przykład 2 — użycie MediaQuery z viewPadding dla poprawnego umieszczenia treści z uwzględnieniem systemowych odstępów.
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(),
);
}
W tym przykładzie padding otacza treść w Padding, używając systemowych odstępów. top uwzględnia pasek stanu i notch, left/right — bezpieczne strefy. bottom nie jest uwzględniony, ponieważ Scaffold zwykle sam obsługuje dolną nawigację.
Przykład 3 — określenie orientacji i zmiana układu elementów.
Widget build(BuildContext context) {
final isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
return isPortrait
? const Column(
children: [HeaderBanner(), ContentList()],
)
: const Row(
children: [HeaderBanner(), ContentList()],
);
}
W portrait mode elementy są ułożone pionowo (Column), w landscape — poziomo (Row). Takie podejście daje najlepsze wykorzystanie przestrzeni przy obrocie urządzenia.
Podsumowanie: MediaQuery — główne narzędzie do budowania adaptacyjnych układów. Zawsze uwzględniaj systemowe odstępy, breakpoints i orientację przy tworzeniu interfejsów Flutter.
Błąd 1: wywołanie MediaQuery.of(context) poza kontekstem, gdzie ustawiono MediaQuery. Jeśli widget znajduje się wyżej niż MediaQuery w drzewie, wywołanie prowadzi do błędu wykonania. Rozwiązanie: zawsze wywoływać MediaQuery.of(context) wewnątrz widgetów owiniętych MaterialApp lub CupertinoApp, gdzie MediaQuery jest ustawiony jako korzenny widget.
Błąd 2: zapominanie o safe area. Programiści używają MediaQuery.size do rozmieszczania elementów bez uwzględniania systemowych odstępów. Na urządzeniach z notch lub gesture navigation treść znajduje się pod paskiem stanu. Rozwiązanie: odejmować MediaQuery.of(context).padding od współrzędnych pozycjonowania.
Błąd 3: sztywne przypisanie do rozmiarów. Używanie MediaQuery.of(context).size.width do określania dokładnych rozmiarów elementów (width: size.width * 0.3) działa tylko na urządzeniach jednego form factora. Na desktopie lub tablecie układ wygląda nienaturalnie. Rozwiązanie: używać breakpoints w połączeniu z Expanded i Flexible dla elastycznego układu, a nie sztywnych procentów.
Błąd 4: ignorowanie textScaleFactor. Przy zwiększeniu systemowej czcionki przez użytkownika interfejs może się zepsuć — teksty wychodzą poza granice kontenerów. Rozwiązanie: sprawdzać MediaQuery.of(context).textScaleFactor i przy wartościach powyżej 1.3 przełączać układ na prostszy z przewijaniem.
Podsumowanie: MediaQuery — potężne, ale subtelne narzędzie. Uwzględniaj systemowe odstępy, orientację i ustawienia dostępności, aby interfejs wyglądał poprawnie na wszystkich urządzeniach.
Często zadawane pytania
MediaQuery.size — całkowity rozmiar ekranu lub okna aplikacji w logicznych pikselach. MediaQuery.viewInsets — obszar przykryty systemową klawiaturą. Do obliczenia dostępnej przestrzeni bez klawiatury: size.height - viewInsets.bottom.
LayoutBuilder podaje rozmiary rodzica, a nie ekranu jako całości. Używaj LayoutBuilder, gdy rozmiary widgetu zależą od dostępnej przestrzeni wewnątrz konkretnego rodzica, a MediaQuery — gdy potrzebne są globalne metryki ekranu.
Automatycznie. Przy obrocie urządzenia Flutter aktualizuje MediaQueryData i przebudowuje poddrzewo. Właściwość orientation zmienia się, a builder wszystkich subskrybujących widgetów jest wywoływany z nowymi danymi.
Tak. Otaczając część widgetów w MediaQuery z nadpisanymi danymi przez MediaQuery.removePadding, MediaQuery.removeViewInsets lub MediaQuery z innym Data. Stosuje się to do osadzania w iframe lub trybach preview.
Do testów Flutter udostępnia setScreenSize i otoczkę MediaQuery w środowisku testowym. Do widget-testów otaczaj testowany komponent w MaterialApp lub MediaQuery z danymi testowymi, aby kontrolować rozmiary ekranu.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również