Адаптивная вёрстка
Одно и то же приложение FlutterFlow работает на телефоне, планшете и в браузере — и на каждом экран должен выглядеть уместно. Ниже разобраны приёмы, которые это обеспечивают.
Примеры идут в одном сквозном сценарии и опираются друг на друга, поэтому читать их лучше по порядку.
Глобальные свойства
Начнём с наглядного: посмотрим, как меняются ширина и высота экрана при переключении устройств в Test Mode.
Создайте проект. На домашней странице внутри Column добавьте два виджета Text — «Screen Width» и «Screen Height».

Теперь выведем рядом сами значения. Каждому Text задайте значение из переменной и выберите Combine Text. Первой частью пусть будет «Screen Width: » или «Screen Height: ».
Второй частью добавьте ещё одно значение из переменной: выберите Global Properties, а в списке — Screen Width или Screen Height. В них лежат текущие размеры экрана. Повторите для второго виджета.

Переключитесь в Test Mode и смените устройство — значения обновятся.
Экраны десктопных размеров:

Экраны телефонов:

Смысл в том, что размеры экрана всегда доступны как глобальные свойства — на них можно строить любую логику интерфейса.
Expanded и Flex
Базовый приём адаптивности: не задавать потомкам Row и Column фиксированные размеры без крайней необходимости.
Возьмём верхнюю панель веб-версии: название страницы, значки навигации и строка поиска. Строка поиска растягивается по доступной ширине, потому что размеры потомков заданы относительно свободного места, а не в пикселях.
Дерево виджетов для такой панели:
- Container (webHeader)
- Row
- Row
- TextField (searchBar)
- IconButton
Второй Row раскладывается дальше:
- Row 2
- Text (pageName)
- Row 3 (navIcons)
- IconButton
- IconButton
- IconButton

Сейчас строка поиска забирает всё свободное место, а нам нужно, чтобы Row 2 и searchBar делили его поровну.
Задайте Row 2 свойство Expansion = Flexible (средний значок) и Flex = 1. То же самое сделайте для searchBar. Теперь свободное место — то, что осталось после значка поиска справа, — делится между ними в отношении 1:1.

Поменяйте ширину окна и посмотрите, как это ведёт себя на разных размерах.
Второй сценарий: строка поиска должна занимать ровно 40% ширины экрана, а Row 2 — всё, что осталось.
Задайте searchBar ширину 40% и Expansion = Default (первый значок).

А Row 2 установите Expansion = Expanded (третий значок). Теперь Row 2 занимает всё место, оставшееся после 40% строки поиска и значка справа.
Строке поиска здесь заодно добавлены отступы и оформление.

Расстояние между pageName и navIcons подтягивается настройкой MainAxisAlignment = Space Between (последний значок).
Wrap
Второй приём для ряда или столбца с несколькими элементами — виджет Wrap.
Возьмём Row с карточками категорий.

На узком экране карточки начинают обрезаться по краям:
Лечится заменой родительского Row на Wrap. В его свойствах задайте Direction = Horizontal — и карточки, которым не хватило места, аккуратно переедут на следующую строку:
Wrap сам раскладывает потомков в несколько строк или столбцов по мере надобности: содержимое не вылезает за границы и не обрезается ни на десктопе, ни на телефоне.
Точки перелома
Дальше начинаются случаи, когда интерфейс на телефоне и в вебе устроен по-разному. Здесь нужны точки перелома.
Breakpoint — пороговое значение ширины экрана, при переходе через которое раскладка меняется.
Свои значения во FlutterFlow заданы по умолчанию, но их можно изменить.
Настройка точек перелома
Откройте Theme Settings > Design System и найдите раздел Breakpoints — там уже стоят значения по умолчанию.

Дальше они понадобятся постоянно: на них опирается адаптивная видимость.
Видимость Nav Bar и App Bar
Обычно App Bar и Nav Bar нужны на телефоне и планшете, а на десктопе — нет.
Откройте App Settings > Nav Bar & App Bar и включите Show Nav Bar. Появятся значки устройств — телефон, планшет, планшет в альбомной ориентации, десктоп: ими выбирается, где панель показывается.
Разумное значение по умолчанию — только телефон или телефон и планшет.

Теперь прямо в редакторе видно, что навигационная панель появляется только на узких экранах. С App Bar это работает так же.
Адаптивная видимость
Часть проблем осталась: панель навигации показывала одни и те же значки и в шапке, и внизу, а на узком экране элементы шапки слипались и по ним было трудно попасть.
Решение — Responsive Visibility: сделать отдельные AppBar и строку поиска для телефона, оставив текущий вариант для веба.
Допустим, мы собрали виджет mobileAppBar: он разносит заголовок категорий и строку поиска по вертикали и добавляет кнопку возврата. Его нужно включить для телефона и планшета, а webHeader оставить для планшета в альбомной ориентации и десктопа.

Делается это значками устройств в свойствах виджета:
После этого один и тот же экран нормально выглядит и на телефоне, и в браузере — без дублирования страниц под каждую платформу.
Responsive Value
Responsive Value задаёт разные значения одного свойства — ширины, высоты, кегля, отступа — для разных размеров экрана. На запуске приложение смотрит на ширину и подставляет нужное.
- Раскладка — размеры элементов, подогнанные под каждый класс устройств.
- Читаемость — более крупный шрифт на большом экране.
- Воздух — увеличенные отступы на планшете и десктопе.
Выделите виджет, выберите свойство, которое это поддерживает, и нажмите Set from Variable > Responsive Value. Дальше задаются значения для четырёх диапазонов:
- телефон — уже
Breakpoint Small - планшет — уже
Breakpoint Medium - десктоп — уже
Breakpoint Large - широкий экран — шире
Breakpoint Large
При переключении устройств в предпросмотре свойство меняется само.
Границы диапазонов задаются в Theme Settings — см. настройку точек перелома.