MediaQuery — какво е, принцип на работа и адаптивни оформления

Автор: IT Sectr Публикувано: 2026-07-03 Време за четене: 7 мин

MediaQuery — обект във Flutter, предоставящ информация за текущата медийна среда: размер на екрана, ориентация на устройството, плътност на пикселите, системни отстъпи и размер на шрифта. MediaQueryData — контейнер за всички тези метрики, достъпен чрез MediaQuery.of(context). Според официалната документация на Flutter (2026), MediaQuery е основата на адаптивния дизайн: чрез него се определя дали да се показва мобилно или таблетно оформление, изчисляват се отстъпите за safe area и се избират размерите на елементите спрямо екрана.

Основни точки

  • MediaQuery — клас за получаване на метрики на екрана: размер, ориентация, плътност, отстъпи
  • MediaQuery.of(context) — основен начин за достъп до данни чрез BuildContext
  • Size (MediaQuery.size) — ширина и височина на екрана в логически пиксели
  • ViewPadding — системни отстъпи (лента за състояние, прорез, системна навигация)
  • Orientation — портретна или пейзажна ориентация на устройството

Какво е 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

MediaQueryData съдържа десетки свойства, но най-често използваните са тези, които влияят на изграждането на оформлението. Нека разгледаме ключовите.

Size — размер на екрана

MediaQuery.of(context).size връща обект Size с ширина и височина на екрана в логически пиксели (device-independent pixels, dip). Тези стойности не вземат предвид системните отстъпи. За изчисленията на адаптивни оформления, size е основната метрика: на нейна база се определят breakpoints за мобилно, таблетно и десктоп оформление.

ViewPadding — системни отстъпи

ViewPadding — отстъпи, които системата резервира за лентата за състояние, прореза (изрез на екрана), системния навигационен панел и индикатора за начало (на iOS). Без отчитането на тези отстъпи, съдържанието може да се окаже под системните елементи. MediaQuery.of(context).padding връща EdgeInsets, който трябва да се приложи като padding към коренния контейнер на страницата.

ViewInsets — област на клавиатурата

ViewInsets — област на екрана, покрита от софтуерната клавиатура. За полета за въвеждане е критично да се следи viewInsets.bottom, за да се повдигне съдържанието над клавиатурата. Flutter обработва това автоматично в scaffold, но за персонализирани оформления трябва да се използва директно MediaQuery.of(context).viewInsets.

Orientation — ориентация на устройството

Orientation — портретна (portrait) или пейзажна (landscape) ориентация. Определя се чрез сравняване на ширина и височина: ако ширината е по-малка от височината — portrait, иначе — landscape. В производствен код ориентацията се използва за превключване между вертикално и хоризонтално подреждане на елементите.

Заключение: четири ключови свойства — size, viewPadding, viewInsets и orientation — покриват 90% от задачите за адаптивен дизайн. Останалите свойства (textScaleFactor, platformBrightness, devicePixelRatio) се използват за специфични сценарии.

Използване на MediaQuery за адаптивни оформления

MediaQuery — основата на адаптивния дизайн във Flutter. Чрез него се определят breakpoints, оформлението се променя в зависимост от размера на екрана и отстъпите се коригират за различни устройства.

Типичен сценарий: мобилно приложение трябва да покаже списък с продукти. На телефон (ширина < 600dp) — една колона. На таблет (ширина 600–900dp) — две колони. На десктоп (ширина > 900dp) — три колони. MediaQuery.of(context).size.width позволява динамичен избор на броя колони без отделен екран за всеки форм фактор.

Втори сценарий: отчитане на system gesture insets на съвременните устройства. На iPhone с Dynamic Island или Android с gesture navigation, системните отстъпи заемат част от екрана. MediaQuery.of(context).padding връща правилни стойности за всеки тип устройство, а Scaffold ги прилага автоматично чрез body. За персонализирани уиджети, padding трябва да се предаде изрично от MediaQuery.

Трети сценарий: адаптиране към системните настройки за достъпност. MediaQuery.of(context).textScaleFactor показва колко е увеличил потребителят шрифта в настройките. При textScaleFactor > 1.3 оформлението може да се счупи — дълги текстове излизат извън границите на картите. Адаптивните оформления трябва да вземат предвид това и при необходимост да превключат към по-просто оформление.

Заключение: MediaQuery — не просто източник на метрики, а инструмент за изграждане на наистина адаптивни интерфейси. Използвайте го за breakpoints, safe area и отчитане на достъпността.

Примери за код с MediaQuery

Пример 1 демонстрира получаване на размера на екрана и прилагане на breakpoints за избор на брой колони.

dart
int getColumnCount(BuildContext context) {
  final width = MediaQuery.of(context).size.width;
  if (width > 900) return 3;
  if (width > 600) return 2;
  return 1;
}

Горният пример показва функция за избор на броя колони на базата на ширината на екрана. Breakpoints 600 и 900 съответстват на общоприетите стандарти на Material Design за телефони, таблети и десктоп.

Пример 2 — използване на MediaQuery с viewPadding за правилно позициониране на съдържанието с отчитане на системните отстъпи.

dart
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 — определяне на ориентацията и промяна на подреждането на елементите.

dart
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 — основният инструмент за изграждане на адаптивни оформления. Винаги вземайте предвид системните отстъпи, breakpoints и ориентацията при разработка на Flutter интерфейси.

Типични грешки при работа с MediaQuery

Грешка 1: извикване на MediaQuery.of(context) извън контекста, където е зададен MediaQuery. Ако уиджетът се намира над MediaQuery в дървото, извикването води до грешка по време на изпълнение. Решение: винаги извиквайте MediaQuery.of(context) вътре в уиджети, обвити в MaterialApp или CupertinoApp, където MediaQuery е зададен като коренен уиджет.

Грешка 2: забравяне на safe area. Разработчиците използват MediaQuery.size за позициониране на елементи без отчитане на системните отстъпи. На устройства с прорез или gesture navigation, съдържанието попада под лентата за състояние. Решение: извадете MediaQuery.of(context).padding от координатите за позициониране.

Грешка 3: твърда връзка с размерите. Използването на MediaQuery.of(context).size.width за задаване на точни размери на елементи (width: size.width * 0.3) работи само на устройства с един форм фактор. На десктоп или таблет оформлението изглежда неестествено. Решение: използвайте breakpoints в комбинация с Expanded и Flexible за гъвкаво оформление, а не твърди проценти.

Грешка 4: игнориране на textScaleFactor. При увеличение на системния шрифт от потребителя, интерфейсът може да се счупи — текстовете излизат извън границите на контейнерите. Решение: проверявайте MediaQuery.of(context).textScaleFactor и при стойности над 1.3 превключете оформлението на по-проста версия с превъртане.

Заключение: MediaQuery — мощен, но деликатен инструмент. Вземайте предвид системните отстъпи, ориентацията и настройките за достъпност, за да изглежда интерфейсът коректно на всички устройства.

Често задавани въпроси

Каква е разликата между MediaQuery.size и MediaQuery.viewInsets?

MediaQuery.size — общ размер на екрана или прозореца на приложението в логически пиксели. MediaQuery.viewInsets — област, покрита от системната клавиатура. За изчисляване на достъпното пространство без клавиатура: size.height - viewInsets.bottom.

Кога да използваме LayoutBuilder вместо MediaQuery?

LayoutBuilder дава размерите на родителския контейнер, а не на целия екран. Използвайте LayoutBuilder, когато размерите на уиджета зависят от наличното пространство в конкретен родител, а MediaQuery — когато са необходими глобални метрики на екрана.

Как MediaQuery реагира на промяна на ориентацията?

Автоматично. При завъртане на устройството Flutter актуализира MediaQueryData и възстановява поддървото. Свойството orientation се променя и builder-ът на всички абонирани уиджети се извиква с нови данни.

Може ли MediaQuery да се промени за част от приложението?

Да. Чрез обвиване на част от уиджетите в MediaQuery с презаписани данни чрез MediaQuery.removePadding, MediaQuery.removeViewInsets или MediaQuery с други Data. Това се прилага за вграждане в iframe или режими за преглед.

Как MediaQuery влияе на тестването?

За тестове Flutter предоставя setScreenSize и обвивка на MediaQuery в тестовата среда. За уиджет тестове, обвийте тествания компонент в MaterialApp или MediaQuery с тестови данни, за да контролирате размерите на екрана.

Обобщение

  • MediaQuery — централен източник на метрики на екрана във Flutter: размер, ориентация, отстъпи и плътност
  • MediaQuery.of(context) — стандартен начин за достъп до данни чрез текущия BuildContext
  • ViewPadding задължителен за safe area на устройства с прорез и gesture navigation
  • Breakpoints (600, 900dp) — основа на адаптивния дизайн чрез MediaQuery.size.width
  • Orientation превключва подреждането на елементите при завъртане на устройството
  • textScaleFactor отчита системните настройки за достъпност за мащабиране на шрифта
  • Препоръка: винаги проверявайте viewPadding и viewInsets при изграждане на коренни оформления

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също