Як в 2 кроки наблизити адаптивну верстку Flutter до способу побудови XML-макета в Android Studio
Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.
У цій статті мова піде про те, як створити Flutter-додаток що може адаптуватись до різних екранів і орієнтацій. Стаття буде корисна як початківцям, так і досвідченим користувачам Flutter. Перші знайдуть шаблон для вивчення, інші ще один погляд на це питання.
Постановка завдання або проблеми адаптивної верстки
«Роби те, що тобі подобається». Flutter
Звучить як «духовно багатий» мотиватор, але це — реальний погляд розробників фреймворка на цю проблему. У Flutter немає одного рішення в дусі «Ein Volk, ein Reich», тут у розробника повна свобода і можливість вибирати спосіб вирішення цих проблем. Так що дивись, щоб не помиливсь, а опісля не журивсь...
На даний момент Flutter підтримує мобільні платформи (Android, iOs), Web (in beta channel), хоч і рідко, проте використовується і для desktop. Зважаючи на це додаток повинен підтримувати широкий діапазон розмірів пристроїв, щільності пікселів і орієнтації. Також мобільний пристрій (якщо не квадратний) може бути повернутий користувачем в портретну або ландшафтну орієнтацію. Користувачі мобільних пристроїв люблять і вміють це робити під час роботи програми, щоб розглянути детальніше вміст екрану. Так що, щоб не розчаровувати користувача, ми повинні подбати про проблему повороту екрану під час роботи програми.
І при всьому цьому додатку бажано ще й працювати, відображаючи інформацію про свою життєдіяльність, незважаючи на характеристики і параметри пристрою, на яке його занесло, і на те, які дії з ним учворить користувач.
«Змішати, але не збовтувати». Проблема мультиплатформенного дизайну
Рідко зустрінеш дизайнера, який розуміє проблеми мультиплатформенного дизайну. І завдання дизайнера Flutter-додатку — приготувати такий коктейль з елементів мобільного дизайну, який не викликає блювотний рефлекс у користувача.
Тому що потрібно якось поєднати ці елементи зі звичним UX на платформах, на яких їх раніше не було. Наприклад, FAB (floating action button in material design) та інші елементи і підходи дизайну, звичні на мобільних платформах, в браузері (web) та десктопі трохи вновинку, і навпаки — прийоми, звичні для вебу, виглядають дикувато на мобілках.
Зазвичай оновлення дизайну відбуваються ітераційно. Так, дизайнер навряд чи відразу видасть остаточний варіант під всі орієнтації і розміри екрану. Тому потрібно передбачити можливість додавання і зміни, щоб не зачіпали те, що вже працює.
Як це вже працює в Android
Проблема і способи її вирішення відомі. На Android свого часу це називалося чутливий (responsive) дизайн. З цього приводу навіть є навіть цілі гайдлайни: Responsive UI — Layout (правда зараз вже в архіві), Support different screen sizes.
Як це виглядає на практиці для розробника? На самому початку існує один макет до якого в міру необхідності додаємо макети для різних по щільності пікселів пристроїв, а потім обидві орієнтації для кожного типу пристроїв. Ці макети потім вибираються в залежності від того, на якому пристрої (з яким розміром екрану) і в якій орієнтації вони працюють.
Для екранів з великою площею зазвичай використовують макети з більшою кількістю інформації до відображення. Гарний приклад — «master / detail flow» з шаблонів нових додатків в Android Studio. Це класика того, як рекомендується працювати з екранами великої площі in android way.
Чи довго казка мовиться, нумо кодити. Але це ж як же без гарної модної методології обійдемося? Може KISS (keep it simple stupid)? Ніт, то вже не модно, забагато літер. Використаємо BDD.
Реалізація
Наші сценарії:
- Я хочу, щоб в межах одного макета на різних пристроях з різною щільністю пікселів виконувалося масштабування контенту (як при використанні dpi розмірів).
- Я хочу мати можливість додавати макети в будь-якому порядку (зробили макет для landscape — відмінно, використовуємо його всюди, зробили для portrait — відмінно, автоматично підставляємо його для портретної орієнтації).
- Я хочу мати можливість додавати макети як в Android Studio для landscape, для portrait, та для більш широких екранів і більш вузьких.
- Я хочу щоб додавання нових макетів не впливало на існуючі макети.
- Я хочу щоб ланцюжок викликів для макета без мого відома не змінювався з часом.
- Я хочу, щоб логіка вибору макета не змінювалася та її не потрібно було чіпати при додаванні / прибиранні макетів.
- Я хочу, щоб логіка вибору була однаковою і передбачуваною.
Код прикладу, розглянутого в статті і пакет, його реалізує, знаходиться за посиланнями:
пакет: pub.dev/packages/sizer_mod
приклад в папці example: https://github.com/NickZt/sizer_mod/tree/master/ example
Ініціалізація
Почнемо з ініціалізації пакету. Виклик нашої MaterialApp обгортаємо в виклик ініціалізації віджета підстроювання розмірів віджетів під dpi екранів
@override Widget build(BuildContextcontext){ return LayoutBuilder( builder: (context, constraints){ return OrientationBuilder( builder: (context, orientation){ SizerUtil().init(constraints, orientation); return MaterialApp(Цей
Цей код знаходиться в example lib \ main.dart
Крок 1. Налаштування віджетів під змінюваний розмір екрана
Ми хочемо відображати віджети на різних екранах найближче до задуманого при первісному дизайні. Ця частина запозичена з бібліотеки sizer і працює так само як в ній.
Також можна використовувати наступний метод, заснований на SizerUtil.orientation властивості для більш точного налаштування параметрів віджета. Див. в прикладі:
appBar: AppBar( title: SizerUtil.orientation == Orientation.portrait ? const Text('portrait') : Const Text( 'landscape'),),
По результату на AppBar видається заголовок з назвою поточної орієнтації. Цей код знаходиться в example: lib\screens\home_screen.dart
Перевіримо відповідність сценарію:
Цей спосіб виконує наше побажання з пункту 1 списку Наші сценарії: «Я хочу, щоб в межах одного макета на різних пристроях з різною щільністю пікселів виконувалося масштабування контенту (як при використанні dpi розмірів).».
Крок 2. Використовуємо спеціалізований віджет для роботи з різними дозволами екрану і орієнтацією
Підтримка зміни орієнтації і перемикання віджетів під різні розміри екрану реалізована з використанням віджета ResponsiveWidget. У його поля ми підставляємо макет (віджет) для кожної пари розмір/орієнтація. На початку у нього є одне обов’язкове поле (по аналогії з default xml in android) — landscapeLargeScreen. Додаткові віджети під інші значення розмір/орієнтація опційні, тобто їх можна додати в міру їх появи:
landscapeMediumScreen
landscapeSmallScreen
portraitMediumScreen
portraitSmallScreen
portraitLargeScreen
У наведеному нижче прикладі за допомогою віджета WelcomePage створюється сторінка в орієнтації landscape і будується макет з використанням прокрутки контенту в вертикальній площині, а для орієнтації portrait використовується такий же віджет з таким же набором сторінок, тільки контент прокручується в горизонтальній площині:
body: ResponsiveWidget( landscapeLargeScreen: WelcomePage( pageIndex: 0, scrollDirection: Axis.vertical, children:listOfPages, ), portraitLargeScreen: WelcomePage( pageIndex: 0, scrollDirection: Axis.horizontal, children:listOfPages, ),),
Для тих, хто любить очима:
github.com/...ges/portrait_land_mob.gif
https://github.com/NickZt/sizer_mod/raw/master/example/images/ portrait_mob.gif
Ми отримали екран, який має різні макети для портретної і альбомної орієнтації. Коли пристрій змінює орієнтацію, ми перебудовуємо наш макет.
Як ми виявляємо зміни орієнтації? Ми дивимося на відношення ширини до довжини сторінки і в залежності від цього перемикаємо макети.
Перевіримо відповідність сценаріям:
Це виконує наші побажання з пункту 2 по пункт 7 з Наші сценарії
- Я хочу мати можливість додавати макети в будь-якому порядку (зробили макет для landscape — відмінно, використовуємо його всюди, зробили для portrait — відмінно, автоматично підставляємо його для портретної орієнтації).
- Я хочу мати можливість додавати макети як в Android Studio для landscape, для portrait, та для більш широких екранів і більш вузьких.
- Я хочу щоб додавання нових макетів не впливало на існуючі макети.
- Я хочу щоб ланцюжок викликів для макета без мого відома не змінювався з часом.
- Я хочу, щоб логіка вибору макета не змінювалася та її не потрібно було чіпати при додаванні / прибиранні макетів.
- Я хочу, щоб логіка вибору була однаковою і передбачуваною.
Висновки
За рецептом з моєї статті можна приготувати додаток, в якому розмір і орієнтація екрану на всіх
Буду радий спілкуванню по темі (і не по темі теж :)) в коментарях.
У другій частині я збираюся більш детально зупиниться на віджетах, які допомагають зробити додаток адаптивним. А також хочу розповісти про деякі нюанси роботи з ними, в порівнянні з елементами дизайну, прийнятими Android.
Код прикладу, розглянутого в статті і пакет, що реалізує цей спосіб, знаходиться тут, Git репозиторій пакет, приклад — в папці example.
Корисні посилання
Support different screen sizes
Floating action button in material design
Немає коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів