Ответ
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), но это менее предпочтительный способ.
Ответ 18+ 🔞
Ну что за тема, ёпта! Слушай, сейчас объясню про эту MediaQuery, чтобы ты не ходил как пизда с ушами по коду. Это, бля, такой виджет, который тебе всё про устройство расскажет — какой экран, как он повёрнут, где системные отступы и прочую хуйню. Без него адаптивный интерфейс собрать — это как хуй с горы катать, нихуя не получится.
Данные ты вытаскиваешь через 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),
),
// А тут меняем всю компоновку в зависимости от ориентации!
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). Но это, бля, как ебать копать — можно, но неестественно и сложно. Старайся без этого обходиться.