Ответ
Для создания адаптивных интерфейсов во Flutter я использую комбинацию встроенных виджетов и определенных практик. Вот основные инструменты:
-
MediaQuery— отправная точка для получения метрик устройства.final size = MediaQuery.of(context).size; final isPortrait = size.height > size.width; final isTablet = size.shortestSide > 600; // Эмпирическое правило для планшета -
LayoutBuilder— ключевой виджет для создания layout, который зависит от доступных ограничений (constraints) родителя, а не от абсолютных размеров экрана.LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth > 1024) { return DesktopLayout(); } else if (constraints.maxWidth > 600) { return TabletLayout(); } else { return MobileLayout(); } }, ) -
FlexibleиExpanded— для создания гибких макетов внутриRowиColumn.Expandedзаставляет дочерний виджет заполнить всё доступное пространство, аFlexibleпозволяет задать коэффициент гибкости (flex). -
Wrap— автоматически переносит дочерние виджеты на следующую строку или столбец, если не хватает места. Отлично подходит для списков тегов или фильтров. -
AspectRatio— принудительно задает соотношение сторон дочернему виджету (например, для баннеров или изображений).AspectRatio( aspectRatio: 16 / 9, child: Image.network('...'), ) -
FractionallySizedBox— задает размеры в долях (процентах) от доступного пространства.FractionallySizedBox( widthFactor: 0.8, // Займет 80% ширины родителя child: ElevatedButton(...), ) -
OrientationBuilder— реагирует на изменение ориентации устройства.
Моя типичная стратегия:
Я начинаю с мобильного дизайна, а затем, используя LayoutBuilder и проверки на maxWidth, добавляю адаптацию для планшетов и десктопов. Часто я выношу логику определения типа layout (мобильный/планшет/десктоп) в отдельный провайдер или утилитный класс, чтобы не дублировать её по всему приложению. Для очень сложных адаптивных систем можно рассмотреть пакеты вроде responsive_framework или flutter_screenutil, но в большинстве случаев встроенных средств Flutter более чем достаточно.