Управляемая вёрстка под устройства разных размеров
При разработке мобильных приложений может потребоваться учитывать размеры устройства - вёрстка для планшета и смартфона часто отличается. При этом, как правило, поначалу у нас есть вёрстка только под один тп устройства (mobile), а с развитием продукта появляется необходимость уникальной вёрстки для планшетов, а с недавних пор и сворачиваемых устройств (foldable). Кроме того, если ваше приложение поддерживает веб или десктоп, то изменение размеров окна становится типичным сценарием.
Итак, нам необходимо решение, которое позволяет:
- гибко управлять вёрсткой для разных размеров экрана;
- постепенно внедрять поддержку новых форм-факторов;
- реагирует на изменение размеров окна (веб и десктоп).
Для этого нам потребуется виджет следующего вида:
class DeviceLayoutBuilder extends StatelessWidget {
final WidgetBuilder mobile;
final WidgetBuilder foldable;
final WidgetBuilder tablet;
const DeviceLayoutBuilder({
super.key,
required this.mobile,
required this.foldable,
required this.tablet,
});
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size.shortestSide;
if (size > 840) return tablet(context);
if (size > 600) return foldable(context);
return mobile(context);
}
}
В данном случае у нас две контрольные точки размеров, которые "разделяют" вёрстку на три форм-фактора - обычное мобильное устройство, устройство в форм-факторе fold и планшет.
При желании легко можно увеличить количество контрольных точек или изменить их значение.
Как использовать?
Типичный пример использования выглядит следующим образом:
class MyScreen extends StatelessWidget {
const MyScreen({super.key});
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(),
body: DeviceLayoutBuilder(
mobile: (_) => MyMobileContent(),
foldable: (_) => MyFoldableContent(),
tablet: (_) => MyTabletContent(),
),
);
}
Здесь MyMobileContent
, MyFoldableContent
и MyTabletContent
- виджеты, реализующие вёрстку для соответствующего форм-фактора.
Само собой, если на текущий момент у вас нет реализации для какого-то форма-фактора, то можно использовать имеющийся и заменить его на нужный, когда он будет готов:
DeviceLayoutBuilder(
mobile: (_) => MyMobileContent(),
foldable: (_) => MyMobileContent(),
tablet: (_) => MyTabletContent(),
)