Адаптивный дизайн на разных уровнях Flutter.
Адаптивный дизайн очень важен для тех, кто ориентируется на разные платформы, используя единую кодовую базу. И особенно это относится к разработке на Flutter, ведь он нацелен на все основные платформы. Как сделать адаптивный дизайн?
Существует множество способов сделать адаптивный дизайн на Flutter. Самый простой из них — получить информацию с текущего экрана с помощью виджета MediaQuery: Size screenSize = MediaQuery.of(context).size;
Orientation orientation = MediaQuery.of(context)
Адаптивный дизайн на разных уровнях Flutter...
Адаптивный дизайн очень важен для тех, кто ориентируется на разные платформы, используя единую кодовую базу. И особенно это относится к разработке на Flutter, ведь он нацелен на все основные платформы.
Как сделать адаптивный дизайн?
Существует множество способов сделать адаптивный дизайн на Flutter. Самый простой из них — получить информацию с текущего экрана с помощью виджета MediaQuery:
Size screenSize = MediaQuery.of(context).size;
Orientation orientation = MediaQuery.of(context).orientation;
Затем уже по-своему, основываясь на этой информации, создать собственный виджет. Или же использовать пакет, упрощающий этот процесс. Вместе с пакетом обычно предоставляется такой интерфейс:
ResponsiveBuilder( builder: (context, sizingInformation) { // Здесь проверяется информация о размерах и возвращается пользовательский интерфейс if (sizingInformation.deviceScreenType == DeviceScreenType.desktop) { return Container(color:Colors.blue); } if (sizingInformation.deviceScreenType == DeviceScreenType.tablet) { return Container(color:Colors.red); } if (sizingInformation.deviceScreenType == DeviceScreenType.watch) { return Container(color:Colors.yellow); } return Container(color:Colors.purple); }, }, ); } Или же предоставляются некоторые заранее заданные типы экранов:
ScreenTypeLayout.builder( mobile: (BuildContext context) => Container(color:Colors.blue), tablet: (BuildContext context) => Container(color:Colors.yellow), desktop: (BuildContext context) => Container(color:Colors.red), watch: (BuildContext context) => Container(color:Colors.purple), ); (Приведенные выше примеры кода взяты из пакета responsive_builder).
Другой интерфейс, по примеру MaterialStateProperty
При написании адаптивного кода нужно добиться хорошей гибкости. Иногда гибким надо сделать лишь одно значение (например, целое число crossAxisCount в GridView). А иногда нужны совершенно разные виды дизайна пользовательского интерфейса для разных экранов (например, TabBarView для мобильных устройств и Row для настольных компьютеров). Поэтому нужно сделать адаптивным либо целое число,либо виджет, не записывая снова и снова операторы if/switch. Кроме того, люди расходятся во мнениях относительно того, где устанавливать контрольные точки. Поэтому нужно предоставить им самим свободно определять собственные контрольные точки.
Встроенные компоненты Material (например, как в случае с кнопкой ElevatedButton) изменяют свой внешний вид в зависимости от того, нажата кнопка или выбрана, или на нее наведен курсор. Эти компоненты не используют какой-то один экземпляр цвета для цвета фона. За них различные значения цвета, основываясь на внутреннем состоянии компонента, генерирует MaterialStateProperty.
property?.resolve(_states)
А что если аналогичный интерфейс задействовать для целей адаптивности?
Состоянием теперь будет некая целевая конфигурация экрана, называющаяся в нашем случае ScreenScope:
class ScreenScope { final double minWidth; final double maxWidth; final double minHeight; final double maxHeight; final Orientation? orientation; ... } У нас уже имеются заранее заданные параметры этой конфигурации:
mobileScreenScope (0px - 480px width) tabletScreenScope (480px - 840px width) desktopScreenScope (840px - width) mobilePortraitScreenScope (0px - 480px width, portrait) tabletPortraitScreenScope (480px - 840px width, portrait) desktopPortraitScreenScope (840px - width, portrait) mobileLandscapeScreenScope (0px - 840px width, landscape) tabletLandscapeScreenScope (840px - 1200px width, landscape) desktopLandscapeScreenScope (1200px - width, landscape) 
Когда используется только одна контрольная точка:
smallScreenScope (0px - 600px width) bigScreenScope (600px - width) smallPortraitScreenScope (0px - 600px width, portrait) bigPortraitScreenScope (600px - width, portrait) smallPortraitScreenScope (0px - 1000px width, landscape) bigPortraitScreenScope (1000px - width, landscape) То объявляется адаптивный экземпляр, а фактическое значение получается вызовом в нем метода resolve:
GridView.count( crossAxisSpacing: 10, mainAxisSpacing: 10, crossAxisCount: Responsive({ mobileScreenScope: 2, tabletScreenScope: 4, desktopScreenScope: 6 }).resolve(context)!, children: List.generate( 30, (index) => Container(color: Colors.green, child: Text("SOME TEXT"))), ); 
А вот что получается, когда нужно использовать разные виджеты для разных экранов:
Widget widget = Responsive({ mobileScreenScope: mobileWidget, tabletScreenScope: tabletWidget, desktopScreenScope: desktopWidget, }).resolve(context); Чтобы сэкономить вам время, мы сделали вспомогательный виджет ScreenBuilder:
ScreenBuilder( mobile: mobile, tablet: tablet, desktop: desktop, ); ScreenBuilder.builder( mobileBuilder: mobileBuilder, tabletBuilder: tabletBuilder, desktopBuilder: desktopBuilder, ) В его синтаксисе используется WidgetBuilder, чтобы иметь доступ к BuildContext.

Заключение
Вот и все о пакете responsive_property. Цель проста: обеспечить гибкость адаптивного дизайна, избавляя от необходимости написания операторов if.