Что такое MediaQuery в Flutter и для чего она используется?

«Что такое MediaQuery в Flutter и для чего она используется?» — вопрос из категории Flutter виджеты, который задают на 36% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

MediaQuery — это виджет, предоставляющий доступ к метаданным и характеристикам текущего устройства (размер экрана, плотность пикселей, ориентация, системные отступы). Это основной инструмент для создания адаптивного интерфейса в Flutter.

Данные извлекаются через MediaQuery.of(context).

Ключевые свойства:

  • MediaQueryData.size (Size) — доступная ширина и высота экрана.
  • MediaQueryData.orientation (Orientation) — портретная или альбомная ориентация.
  • MediaQueryData.padding (EdgeInsets) — системные отступы (например, для статус-бара, «челки» или панели навигации).
  • MediaQueryData.textScaleFactor (double) — коэффициент масштабирования текста, заданный пользователем в настройках системы.
  • MediaQueryData.devicePixelRatio (double) — плотность пикселей устройства.

Практический пример адаптивного дизайна:

Widget build(BuildContext context) {
  // Получаем данные о медиа
  final mediaData = MediaQuery.of(context);
  final screenWidth = mediaData.size.width;
  final isLandscape = mediaData.orientation == Orientation.landscape;

  // Логика в зависимости от размера экрана (брейкпоинты)
  final isWideScreen = screenWidth > 600;

  return Scaffold(
    body: Container(
      // Адаптивная ширина
      width: isWideScreen ? 400 : double.infinity,
      padding: EdgeInsets.all(isWideScreen ? 24.0 : 16.0),
      child: Column(
        children: [
          // Текст с учетом пользовательских настроек масштаба
          Text(
            'Адаптивный заголовок',
            style: TextStyle(fontSize: 20 * mediaData.textScaleFactor),
          ),
          // Меняем layout в зависимости от ориентации
          if (isLandscape)
            Row(children: [Expanded(child: Chart()), Expanded(child: Details())])
          else
            Column(children: [Chart(), Details()]),
        ],
      ),
    ),
  );
}

Важно: MediaQuery.of(context) зависит от BuildContext. Ее вызов в build() безопасен. Для использования в initState() данные нужно получать через MediaQueryData.fromWindow(WidgetsBinding.instance.window), но это менее предпочтительный способ.