Адаптивная вёрстка

Одно и то же приложение FlutterFlow работает на телефоне, планшете и в браузере — и на каждом экран должен выглядеть уместно. Ниже разобраны приёмы, которые это обеспечивают.

Примеры идут в одном сквозном сценарии и опираются друг на друга, поэтому читать их лучше по порядку.

Глобальные свойства

Начнём с наглядного: посмотрим, как меняются ширина и высота экрана при переключении устройств в Test Mode.

Создайте проект. На домашней странице внутри Column добавьте два виджета Text — «Screen Width» и «Screen Height».

screen-width-height.avif

Теперь выведем рядом сами значения. Каждому Text задайте значение из переменной и выберите Combine Text. Первой частью пусть будет «Screen Width: » или «Screen Height: ».

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

setting-global-properties.avif

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

Экраны десктопных размеров:

running-app-on-test-mode-for-desktop-device-sizes.avif

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

running-app-on-test-mode-for-mobile-device-sizes.avif

Смысл в том, что размеры экрана всегда доступны как глобальные свойства — на них можно строить любую логику интерфейса.

Expanded и Flex

Базовый приём адаптивности: не задавать потомкам Row и Column фиксированные размеры без крайней необходимости.

Возьмём верхнюю панель веб-версии: название страницы, значки навигации и строка поиска. Строка поиска растягивается по доступной ширине, потому что размеры потомков заданы относительно свободного места, а не в пикселях.

Дерево виджетов для такой панели:

- Container (webHeader)
       - Row
             - Row
             - TextField (searchBar)
             - IconButton

Второй Row раскладывается дальше:

- Row 2
    - Text (pageName)
    - Row 3 (navIcons)
        - IconButton
        - IconButton
        - IconButton

row-breakdown.avif

Сейчас строка поиска забирает всё свободное место, а нам нужно, чтобы Row 2 и searchBar делили его поровну.

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

test-expansion.avif

Поменяйте ширину окна и посмотрите, как это ведёт себя на разных размерах.

Второй сценарий: строка поиска должна занимать ровно 40% ширины экрана, а Row 2 — всё, что осталось.

Задайте searchBar ширину 40% и Expansion = Default (первый значок).

set-searchbar.png

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

Строке поиска здесь заодно добавлены отступы и оформление.

enhanced-searchbar.avif

Расстояние между pageName и navIcons подтягивается настройкой MainAxisAlignment = Space Between (последний значок).

Wrap

Второй приём для ряда или столбца с несколькими элементами — виджет Wrap.

Возьмём Row с карточками категорий.

row-of-cards.avif

На узком экране карточки начинают обрезаться по краям:

Лечится заменой родительского Row на Wrap. В его свойствах задайте Direction = Horizontal — и карточки, которым не хватило места, аккуратно переедут на следующую строку:

Wrap сам раскладывает потомков в несколько строк или столбцов по мере надобности: содержимое не вылезает за границы и не обрезается ни на десктопе, ни на телефоне.

Точки перелома

Дальше начинаются случаи, когда интерфейс на телефоне и в вебе устроен по-разному. Здесь нужны точки перелома.

Breakpoint — пороговое значение ширины экрана, при переходе через которое раскладка меняется.

Свои значения во FlutterFlow заданы по умолчанию, но их можно изменить.

Настройка точек перелома

Откройте Theme Settings > Design System и найдите раздел Breakpoints — там уже стоят значения по умолчанию.

custom-responsive-breakpoints.avif

Дальше они понадобятся постоянно: на них опирается адаптивная видимость.

Видимость Nav Bar и App Bar

Обычно App Bar и Nav Bar нужны на телефоне и планшете, а на десктопе — нет.

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

Разумное значение по умолчанию — только телефон или телефон и планшет.

appbar-navbar-visibility.webp

Теперь прямо в редакторе видно, что навигационная панель появляется только на узких экранах. С App Bar это работает так же.

Адаптивная видимость

Часть проблем осталась: панель навигации показывала одни и те же значки и в шапке, и внизу, а на узком экране элементы шапки слипались и по ним было трудно попасть.

Решение — Responsive Visibility: сделать отдельные AppBar и строку поиска для телефона, оставив текущий вариант для веба.

Допустим, мы собрали виджет mobileAppBar: он разносит заголовок категорий и строку поиска по вертикали и добавляет кнопку возврата. Его нужно включить для телефона и планшета, а webHeader оставить для планшета в альбомной ориентации и десктопа.

responsive-visibility.avif

Делается это значками устройств в свойствах виджета:

После этого один и тот же экран нормально выглядит и на телефоне, и в браузере — без дублирования страниц под каждую платформу.

Responsive Value

Responsive Value задаёт разные значения одного свойства — ширины, высоты, кегля, отступа — для разных размеров экрана. На запуске приложение смотрит на ширину и подставляет нужное.

инфо
Где пригодится
  • Раскладка — размеры элементов, подогнанные под каждый класс устройств.
  • Читаемость — более крупный шрифт на большом экране.
  • Воздух — увеличенные отступы на планшете и десктопе.

Выделите виджет, выберите свойство, которое это поддерживает, и нажмите Set from Variable > Responsive Value. Дальше задаются значения для четырёх диапазонов:

  • телефон — уже Breakpoint Small
  • планшет — уже Breakpoint Medium
  • десктоп — уже Breakpoint Large
  • широкий экран — шире Breakpoint Large

При переключении устройств в предпросмотре свойство меняется само.

совет
Свои границы

Границы диапазонов задаются в Theme Settings — см. настройку точек перелома.

перевод официальной документации FlutterFlow

обновлено

⌕ ESC