Из этого руководства вы узнаете, как с помощью Flutter создавать приложения, которые автоматически подстраиваются под изменение размера и положения экрана пользовательского устройства.

Основы адаптивного дизайна на Flutter

Скачать материалы

Версии программного обеспечения: Dart 2, Flutter 1.7, Android Studio 3.5

Внешний вид приложения может изменяться при запуске на мобильном устройстве. Пользователь может поворачивать смартфон, вызывать всплывающую клавиатуру. Чтобы программой было одинаково удобно пользоваться как на больших, так и на маленьких дисплеях, верстка приложения должна автоматически приспосабливаться к изменению параметров экрана пользовательского устройства. Если приложение разработано с учетом концепции адаптивного дизайна, проблем с отображением на различных экранах не возникнет.

  • Приступаем к работе
  • Использование MediaQuery для управления макетом
  • Использование виджетов в адаптивном дизайне
    • Применение LayoutBuilder и OrientationBuilder
  • Автоматическое масштабирование текста с помощью родительских виджетов
    • Использование FittedBox
  • Ограничения для вложенных виджетов
    • Использование соотношения сторон AspectRatio
  • Использование макета CustomMultiChildLayout
  • Что еще будет полезно изучить
  • В этом руководстве мы рассмотрим следующие темы:

    1. Создание чат-приложения, дизайн которого реагирует на изменение параметров экрана.
    2. Использование виджетов MediaQuery, LayoutBuilder, OrientationBuilder, FittedBox и AspectRatio.
    3. Адаптация верстки к изменению положения экрана.
    4. Адаптивное масштабирование текста.
    5. Привязка вложенных виджетов к колонкам.
    6. Изучение концепции виджета CustomMultiChildLayout.

    Примечание: это руководство предполагает, что читатель уже знаком с базовыми приемами разработки на Flutter. Если это не так, начните изучение фреймворка со статьи «Начинаем работать с Flutter». Также понадобятся навыки использования Android Studio в связке с Flutter.

    Что такое адаптивный дизайн

    Концепция адаптивного дизайна заключается в использовании кода, который соответствующим образом подстраивается под различные изменения макета страницы. Собственные наборы средств разработки (SDK) мобильных платформ iOS и Android решают эту проблему с помощью универсальных макетов верстки.

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

    Поддержка различных типов устройств и параметров дисплея

    Основы адаптивного дизайна на Flutter

    Пользователи могут запустить ваше Flutter-приложение на самых разных устройствах – смартфонах, планшетах, телевизорах и умных часах (когда в них появится поддержка подобных программ). Даже среди смартфонов существует достаточно большой разброс по размерам и разрешению экрана. Разработчику нужно удостовериться в том, что приложение будет корректно работать на любом устройстве, с любыми параметрами экрана. Кроме того, можно предусмотреть различные дизайны интерфейса для разных пользовательских устройств и размеров дисплея.

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

    Адаптация интерфейса к всплывающей клавиатуре

    Ваше приложение может включать в себя текстовые поля. Для ввода текста вызывается всплывающая клавиатура, а вместе с ней появляется несколько проблем с макетом страницы. Android решает эти проблемы с помощью изменения конфигурации клавиатуры. iOS отслеживает изменения в состоянии программной клавиатуры. В Flutter за автоматическую адаптацию интерфейса к статусу клавиатуры отвечает класс Scaffold.

    В частности, Scaffold автоматически меняет размер нижней вставки, освобождая пространство для клавиатуры. Эту функцию можно отключить, если в свойстве resizeToAvoidBottomInset указать параметр false. Подробнее на тему взаимодействия класса Scaffold с клавиатурой можно прочитать здесь.

    Обработка изменений положения экрана

    Общеизвестный факт – пользователи любят вертеть свои смартфоны и так, и эдак. Реагирование приложения на изменение ориентации экрана можно отключить, заморозив интерфейс в горизонтальном или вертикальном положении. Но в этом случае приложение станет неудобным, и это может серьезно испортить пользовательский опыт.

    В Flutter за обработку изменения ориентации отвечает MediaQuery, который помогает автоматически перестраивать макет страницы. Библиотеки MaterialApp и WidgetsApp используют MediaQuery по умолчанию. Подробнее о MediaQuery можно почитать здесь.

    Мы выяснили причины для использования адаптивной концепции в дизайне, теперь пора переходить к рассмотрению вопроса о том, как виджеты Flutter помогают в разработке подобного интерфейса.

    Приступаем к работе

    Загрузите стартовый проект, нажав на кнопку «Скачать материалы». Затем откройте проект в Android Studio 3.4 или выше. Если вы пользуетесь средой разработки VS Code, некоторые инструкции будут отличаться.

    У вас должна быть установлена версия Flutter, 1.5 или выше. Не забудьте установить все нужные зависимости; в случае их отсутствия Android Studio продемонстрирует сообщение «Packages get’ has not been run» («Нужные пакеты не были установлены»).

    Как вы обнаружите, стартовый пакет уже включает в себя заготовки для различных частей чат-приложения.

    Использование MediaQuery для управления макетом

    Сначала мы попробуем использовать MediaQuery для адаптации интерфейса. Это всего лишь один из возможных вариантов реализации адаптивного дизайна, мы рассмотрим другие методы чуть позже.

    Перейдите в директорию lib, откройте файл ChatListPage.dart. Замените код метода build(BuildContext context) на приведенный ниже:

    // 1 var hasDetailPage =     MediaQuery.of(context).orientation == Orientation.landscape; // 2 Widget child;  if (hasDetailPage) {   // 3   child = Row(     children: [       // 4       SizedBox(         width: 250,         height: double.infinity,         child: _buildList(context, hasDetailPage),       ),       // 5       Expanded(child: _buildChat(context, selectedIndex)),     ],   ); } else {   // 6   child = _buildList(context, hasDetailPage); }  return Scaffold(   appBar: AppBar(     title: Text("Chats"),   ),   body: SafeArea(     // 7     child: child,   ), ); 

    Начинаем работать с Flutter

    Этот код задает адаптивный дизайн для страницы чата, используя MediaQuery. Рассмотрим подробнее, как именно это происходит:

    1. Сначала код проверяет ориентацию страницы. Если это горизонтальное положение, передаются соответствующие параметры страницы.
    2. Объявляется дочерний виджет для использования на следующих этапах.
    3. Если параметры страницы получены, дочерний виджет становится рядом виджетов.
    4. Ряд содержит список чатов в качестве первого элемента.
    5. Второй элемент ряда отображает страницу чата с диалогами.
    6. Если параметры страницы еще не переданы, дочерний виджет будет списком чатов.
    7. Здесь дочерний виджет становится вложенным виджетом SafeArea.

    Запустите выполнение проекта, и вы увидите вот такую страницу в вертикальном положении:

    Основы адаптивного дизайна на Flutter

    И такую страницу при горизонтальной ориентации экрана:

    Основы адаптивного дизайна на Flutter

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

    Использование виджетов в адаптивном дизайне

    Как уже отмечалось выше, есть и другие виджеты, которые помогают добиться такого же эффекта, как и MediaQuery. Например, LayoutBuilder позволяет делать то же самое, как вы сейчас увидите. Кроме того, на этом этапе мы сможем исправить некоторые недостатки приложения – к примеру, сейчас надписи на аватарах пользователей не масштабируются.

    Применение LayoutBuilder и OrientationBuilder

    LayoutBuilder и OrientationBuilder – альтернатива MediaQuery в части адаптации к ориентации экрана пользовательского устройства. Рассмотрим, как именно они работают. Начнем с LayoutBuilder.

    Прежде всего, откройте файл ChatListPage.dart, как вы делали на предыдущем этапе. Замените код build(…) наследующий:

    return Scaffold(   appBar: AppBar(     title: Text("Chats"),   ),   body: SafeArea(     // 1     child: LayoutBuilder(builder: (builder, constraints) {       // 2       var hasDetailPage = constraints.maxWidth > 600;        if (hasDetailPage) {         // 3         return Row(           children: [             // 4             SizedBox(               width: 250,               height: double.infinity,               child: _buildList(context, hasDetailPage),             ),             // 5             Expanded(child: _buildChat(context, selectedIndex)),           ],         );       } else {         // 6         return _buildList(context, hasDetailPage);       }     }),   ), ); 

    Приведенный выше код заново определяет макет страницы, в этот раз с использованием LayoutBuilder. Рассмотрим подробнее, что именно мы только что сделали:

    1. Сначала вы объявили LayoutBuilder дочерним виджетом SafeArea.
    2. Затем код проверяет, получены ли параметры страницы, если ее максимальная ширина превосходит 600 пикселей. Если ширина родительского виджета больше 600, передаются параметры страницы.
    3. Если параметры уже получены, дочерний виджет становится рядом виджетов.
    4. Первый элемент ряда – список чатов.
    5. Второй элемент показывает диалоги.
    6. И, наконец, если параметры страницы еще не получены, отображается список чатов.

    Организация файлов приложения Flutter

    Запустите сборку и выполнение проекта. Как и на предыдущем этапе, вы получите различные макеты страниц при различной ориентации экрана.

    Если вы также хотите опробовать OrientationBuilder, замените строки, относящиеся к объявлению LayoutBuilder и настройкам hasDetailPage на следующий код:

    child: OrientationBuilder(builder: (builder, orientation) {     var hasDetailPage = orientation == Orientation.landscape; 

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

    Запустите сборку и выполнение кода. Вы получите такой же интерфейс, как и раньше. Как видите, любой из использованных нами приемов обеспечивает одинаковое решение проблемы с ориентацией и размером экрана.

    Далее мы исправим текст, который не масштабируется вместе с аватаром.

    Автоматическое масштабирование текста с помощью родительских виджетов

    Как вы уже заметили на скриншотах горизонтального макета приложения, инициалы пользователей в цветных квадратах не увеличиваются в соответствии с размерами аватаров. Просто увеличить размер шрифта нельзя, текст выйдет за пределы аватара. Правильный способ увеличения размера шрифта – масштабирование текста в соответствии с масштабом родительского виджета. Справиться с этой задачей поможет виджет FittedBox.

    Использование FittedBox

    Откройте файл AvatarImageView.dart в директории lib/widgets и обратите внимание на код в _buildContent(Color textColor). Здесь находится текстовый виджет, отображающий инициалы пользователя. Размер шрифта – 14. Оберните текстовый виджет в FittedBox, как показано ниже:

    // 1 return FittedBox(   // 2   fit: BoxFit.contain,   // 3   child: Text(     initials,     style: TextStyle(color: textColor, fontSize: 14),   ), ); 

    Это заставит виджет Text заполнить родительский виджет и следовать правилам в BoxFit.contain. Рассмотрим код построчно:

    1. Сначала вы сделали FittedBox родительским виджетом Text.
    2. Затем вы устанавливаете для contain возможность максимального масштабирования без выхода за границы виджета.
    3. И, наконец, вы сделали Text дочерним виджетом.

    Запустите сборку и выполнение проекта. В горизонтальной ориентации вы получите такой макет страницы:

    Основы адаптивного дизайна на Flutter

    Как видите, теперь текст масштабируется правильно. Для других случаев вы можете использовать другие типы BoxFit. Скриншот, приведенный ниже, показывает различные варианты масштабирования:

    Основы адаптивного дизайна на Flutter

    Как написать 2D игру «Змейка» на Flutter

    Ограничения для вложенных виджетов

    В приложении есть иконка скрепки – нажатие на нее должно открывать фотогалерею, из которой можно выбрать изображение для прикрепления к сообщению. Как правило, пользователи хотят, чтобы галерея открывалась поверх чата, не скрывая его из виду полностью.

    Пока что такой функции в нашем приложении нет. Нажмите на иконку вложения, и при вертикальном положении экрана вы увидите следующее:

    Основы адаптивного дизайна на Flutter

    В горизонтальном варианте экран выглядит так:

    Основы адаптивного дизайна на Flutter

    Использование соотношения сторон AspectRatio

    Галерея не работает, и мы займемся исправлением этой ошибки. Прежде всего, откройте файл ConversationPage.dart в директории lib. Найдите строку SquareGallery(), отмеченную примечанием TODO.

    Виджет галереи не отображается потому, что сейчас он является вложенным элементом Column и к тому же не имеет параметров для определения собственного размера. Для исправления этой ситуации оберните виджет в AspectRatio для установки соотношения сторон. Замените строку SquareGallery() на следующий код:

    AspectRatio(   aspectRatio: 3,   child: SquareGallery(), ), 

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

    Запустите сборку и выполнение программы. Теперь после нажатия на иконку вложения вы получите следующий интерфейс в вертикальном положении экрана:

    Основы адаптивного дизайна на Flutter

    И следующий дизайн в горизонтальной ориентации:

    Основы адаптивного дизайна на Flutter

    Примите поздравления: вы исправили все недочеты, связанные с масштабированием. Дизайн чат-приложения стал полностью адаптивным.

    Использование макета CustomMultiChildLayout

    В дополнение к основным виджетам для создания адаптивного дизайна Flutter предоставляет разработчикам возможность реализовать собственный адаптивный макет с помощью CustomMultiChildLayout. Мы бегло рассмотрим этот способ, но лишь в теории, поскольку CustomMultiChildLayout – очень обширная тема, а здесь мы ограничиваемся основами.

    Посмотрите на этот код:

    CustomMultiChildLayout(   delegate: delegate,   children: widgets, ) 

    Здесь вы объявляете CustomMultiChildLayout с делегацией функций. Делегатом может быть объект класса, какпоказано ниже:

    // 1 class RWDelegate extends MultiChildLayoutDelegate {   // 2   @override   void performLayout(Size size) {     // Do your layout here   }    // 3   @override   bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) => false; } 

    Вот что делает этот код:

    1. Сначала вы объявляете подкласс MultiChildLayoutDelegate.
    2. Затем переопределяете метод performLayout, который определяет расположение вложенных виджетов на странице с использованием двух других методов, layoutChild и positionChild.
    3. И, наконец, вы получаете логический параметр от shouldRelayout, который определяет, нужно ли заново выполнить раскладку элементов.

    Полную документацию по виджету можно изучить здесь, а по работе с делегированием – здесь.

    Что еще будет полезно изучить

    Все материалы руководства можно скачать, нажав на кнопку «Скачать материалы».

    Если тема адаптивного дизайна на Flutter вам интересна, ознакомьтесь с официальной документацией по этой ссылке и подборкой методов дизайна здесь.

    Также вам может пригодиться изучение особенностей масштабирования текста на мобильных платформах. Надеюсь, это руководство вам понравилось. Если у вас есть вопросы или замечания, сообщите о них в комментариях.

    Скачать материалы

    Наталья Кайдаавтор-переводчик статьи «Responsive Design for Flutter: Getting Started»

    Источник: www.internet-technologies.ru

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.