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 — системные отступы (статус-бар, notch, системная навигация)
  • 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 — отступы, которые система резервирует для статус-бара, notch (выреза на экране), системной навигационной панели и индикатора дома (на iOS). Без учёта этих отступов содержимое может оказаться под системными элементами. MediaQuery.of(context).padding возвращает EdgeInsets, который нужно применять как padding к корневому контейнеру страницы.

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

ViewInsets — область экрана, перекрытая программной клавиатурой. Для полей ввода критично отслеживать viewInsets.bottom, чтобы поднимать содержимое над клавиатурой. Flutter автоматически обрабатывает это в scaffold, но для кастомных макетов нужно использовать MediaQuery.of(context).viewInsets напрямую.

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

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

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

Использование MediaQuery для адаптивных макетов

MediaQuery — основа адаптивного дизайна во Flutter. Через него определяют breakpoints, переключают layout в зависимости от размера экрана и корректируют отступы для разных устройств.

Типичный сценарий: мобильное приложение должно отображать список товаров. На телефоне (ширина < 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 учитывает статус-бар и notch, 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()],
        );
}

В portrait mode элементы расположены вертикально (Column), в landscape — горизонтально (Row). Такой подход даёт наилучшее использование пространства при повороте устройства.

Вывод: MediaQuery — основной инструмент для построения адаптивных макетов. Всегда учитывайте системные отступы, breakpoints и ориентацию при разработке Flutter-интерфейсов.

Типовые ошибки при работе с MediaQuery

Ошибка 1: вызов MediaQuery.of(context) вне контекста, где установлен MediaQuery. Если виджет находится выше MediaQuery в дереве, вызов приводит к ошибке времени выполнения. Решение: всегда вызывать MediaQuery.of(context) внутри виджетов, обёрнутых MaterialApp или CupertinoApp, где MediaQuery установлен корневым виджетом.

Ошибка 2: забывчивость про safe area. Разработчики используют MediaQuery.size для расположения элементов без учёта системных отступов. На устройствах с notch или 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 или preview-режимов.

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

Для тестов Flutter предоставляет setScreenSize и обёртку MediaQuery в test-окружении. Для виджет-тестов оборачивайте тестируемый компонент в MaterialApp или MediaQuery с тестовыми данными, чтобы контролировать размеры экрана.

Итоги

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

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

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также