Егор Долгов
Егор Долгов
(обновлено )
За все время: 7346 просмотров, 3664 посетителя.
За последние 30 дней: 98 просмотров, 66 посетителей.

Создание адаптивного пользовательского интерфейса

Автор оригинального текста Aloïs Deniel
перевод статьи https://aloisdeniel.com/#/posts/adaptative-ui

Недавно я представил доклад на конференции FlutterVikings, в котором подробно объяснил, о чем вам следует думать в первую очередь при создании пользовательского интерфейса (запись доступна на YouTube).

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

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

Единого и однозначного определения адаптивного дизайна не существует. Я считаю, что термин «отзывчивый дизайн» можно выбрать для контраста с адаптивным дизайном; тем более, что мы с ним часто сталкиваемся.

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

Мобильные устройства предоставили множество новых вариантов использования. У пользователей теперь имеется множество устройств с разными экранами, но помимо этого:

К счастью, Flutter предоставляет все необходимые инструменты для того, чтобы справиться со всеми этими проблемами.

Платформа

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

Наиболее легко отследить платформу пользователя через класс Platform. Поскольку web платформа имеет другую систему сборки, вам, возможно, придется также проверить константу kIsWeb.

Замечание от автора перевода: обращение к полям Platform в web приведет к Exception, по этому важно в условном операторе вначале проверить что это не web платформа, или как в данном примере до Platform не дойдет если это web.

Команда Flutter разработала две библиотеки виджетов для помощи в адаптации визуальных элементов вашего приложения.

В дополнение к распространенному дизайну Material, который идет с Android, пакет Cupertino имитирует нативные компоненты пользовательского интерфейса iOS. Использование этих компонентов может обеспечить максимально удобный интерфейс для пользователей iOS.

К сожалению, пока что еще не существует библиотек Windows, macOS, Linux, однако, никто и ничто не останавливает вас от создания собственной системы дизайна, что может стать наиболее простым решением для адаптации ваших интерфейсов.

Дисплей

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

MediaQuery

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

Поскольку это InheritedWidget, у вас будет доступ к нему из любой точки дерева виджетов. Если вы не знакомы с таким видом виджетов (я настоятельно рекомендую посмотреть это видео из цикла Flutter 101), любой дочерний виджет из дерева, читающий данные InheritedWidget, будет перестроен автоматический каждый раз, когда эти данные меняются.

Размер экрана

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

Для получения актуального размера окна приложения, используйте свойство size из MediaQuery. Опять-таки, если размер окна меняется, метод построение вызывается автоматически.

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

Разрешение экрана

Определение плотности экрана может помочь вам улучшить ваше приложение для разных устройств.

Каждый экран имеет определенное разрешение в пикселях. Грубо говоря, это то, сколько пикселей вы можете вместить в пространство вашего экрана (к примеру, в квадрат 1х1 дюйм).

Из двух устройств с одинаковыми физическими размерами экрана одно может иметь в четыре раза больше пикселей.

Получить плотность экрана devicePixelRatio из MediaQuery.

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

Отступы экрана

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

Чтобы узнать, какие области экрана ограничены «челкой» и скругленными краями, используйте свойство padding из MediaQuery.

Flutter также дает вам виджет для этой задачи: SafeArea.

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

Специальные возможности (универсальный доступ)

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

И снова эти два свойства доступны в MediaQuery:

Значение textScaleFactor для Text по умолчанию является mediaQuery.textScaleFactor, поэтому попробуйте обновить эти настройки при разработке приложения, чтобы убедиться, что ваши макеты не сломаются.

Темная тема

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

platformBrightness доступна из MediaQuery.

Если вы используете MaterialApp, вы также можете задать lightTheme и darkTheme чтобы автоматически подстроить цветовые схемы для встроенных компонентов.

Интернационализация

Что может более очевидным, чем принятие во внимание языка речи пользователя при создании адаптивного интерфейса!

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

Чтобы получить доступ к языку текущего пользователя, используйте виджет Localizations:

Для интернационализации текста вашего приложения, добавьте в зависимости пакет intl. Он идет с множеством вспомогательных средств, например, DateFormat.

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

Вы можете получить доступ к направлению текста при необходимости:

Пользовательский ввод

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

Синтезатор речи

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

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

Все стандартные виджеты Flutter уже предоставляют семантику или, по крайней мере, есть настройки на уровне виджетов.

Мышь и клавиатура

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

Команда Flutter уже придумала виджеты для таких случаев использования, и одним из самых полезных является Shortcuts, который позволяет запускать обратный вызов при вводе клавишных комбинаций.

Если вам нужен необработанный ввод с клавиатуры, используйте RawKeyboardListener.

Для отслеживания курсора мыши используйте виджет MouseRegion:

Имейте в виду, что указатель мыши намного более точен, чем сенсорные жесты: это возможность уменьшить размер областей взаимодействия, чтобы отображать больше контента для пользователя. Это то, что VisualDensity выполняет в MaterialApp.

Производительность / Взаимодействие

Наконец, некоторые вещи зависят не от самого пользователя, а от его устройства и контекста.

Соединение

В контексте мобильных устройств, статус сети может влиять на многое. Это может быть более производительный wi-fi, а может быть и менее быстрый мобильный интернет.

Очень важно учесть все эти случаи и дать пользователю обратную связь, чтобы улучшить его опыт относительно состояния подключения. К счастью, есть плагин для наблюдения за этими изменениями состояния сети: Connectivity.

Обеспечение автономного режима может потребовать много усилий, но для пользователя это серьезное улучшение.

Анимация

Даже если на самом деле невозможно проверить производительность рендеринга устройства, пользователь может отключить анимацию в своих системных настройках. Это может быть из-за «специальных возможностей», но также и по соображениям производительности. Поэтому важно адаптировать переходы и анимацию вашего приложения на основе этого параметра.

Свойство disableAnimations доступно из MediaQuery:

Советы для улучшения адаптивности

Закончим эту статью некоторыми пунктами, которые помогут вам сделать ваше приложение максимально адаптивным.

1. Предвидеть адаптивность

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

2. Избегайте констант

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

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

Один из способов улучшения — определить класс данных, который централизует все эти свойства, который предоставляется дереву виджетов через InheritedWidget.

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

Эта статья может помочь вам лучше понять этот подход.

3. Максимально разделите ваши виджеты

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

4. Попробуйте DevicePreview!

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

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

Именно поэтому я решил создать пакет Flutter DevicePreview. Это простой виджет, который захватывает все ваше приложение и позволяет переопределить медиа-запрос, чтобы проверить все его особенности. Он также дает вам предварительный просмотр того, как ваше приложение будет работать на популярных устройствах.

DevicePreview имеет открытый исходный код, поэтому не стесняйтесь оставлять свои отзывы, чтобы помочь мне улучшить его!

Демонстрация

Я запустил пример адаптивного приложения с открытым исходным кодом, чтобы дать вам рекомендации по советам, которые я представил здесь.

Все доступно на Github.

Заключение

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

Надеюсь, вам понравилась эта статья, так как это просто адаптация того, что я представил на конференции FlutterViking.

Увидимся!

Подборка заметок