Хабрахабр

[Из песочницы] Разработка UI с помощью Flutter

Привет, Хабр! Представляем вашему вниманию перевод статьи "Building Layouts".

Сегодня мы узнаем:

  • Как работают механики построения UI на Flutter
  • Как верстать экраны горизонтально и вертикально
  • Как сверстать экран, используя Flutter

Результатом сегодняшнего урока будет следующий сверстанный экран

image

Шаг 0: Настройка проекта

Для начала создадим новый проект File -> New Flutter Project -> next, next, next…
Далее необходимо, создать директорию images в корне проекта и положить туда файл с именем lake.jpg — сам файл скачать можно отсюда — link

Сам текст файла можно скачать здесь Так же необходимо поправить конфигурационный файл pubspec.yaml (что-то вроде gradle для android и cocoa pods в iOS, в нем мы можем добавить внешние зависимости).

Исходник проекта можно скачать здесь — его необходимо поместить в файл main.dart

Шаг 1: Диаграмма экрана

Для начала разобьем макет на простые элементы

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

Сперва определим основные крупные элементы. В этом примере — 4 элемента расположены в виде столбца: картина, две строки и блок теста

image

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

image

Каждый из них содержит картинку и текст. Следущий ряд, называемый секцией кнопок, так же имеет 3 дочерних элемента.

image

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

Шаг 2: Построим ряд заголовка

Сперва, мы должны построить левый столбец секции заголовка. Вставка столбца внутри расширяемого виджета растягивает столбец для использования всего оставшегося места в ряду. Установим свойство crossAxisAlignment для CrossAxisAlignment.start для выравнивания столбца к началу строки.

Второй дочерний элемент в столбце это тоже текст, он отображается серым цветом. Размещение строки текста внутри контейнера позволяет активировать отступы. Поместим целую строку в контейнер и добавим отступы по 32 пикселя с каждой стороны. Последние два элемента иконка «звезды» нарисована красным цветом и текст со значением «41». Код для выполнения этих действий представлен ниже

class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { Widget titleSection = Container( padding: const EdgeInsets.all(32.0), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.only(bottom: 8.0), child: Text( 'Oeschinen Lake Campground', style: TextStyle( fontWeight: FontWeight.bold, ), ), ), Text( 'Kandersteg, Switzerland', style: TextStyle( color: Colors.grey[500], ), ), ], ), ), Icon( Icons.star, color: Colors.red[500], ), Text('41'), ], ), ); //...
}

Шаг 3: Построим ряд кнопок

Секция кнопок состоит из 3 столбцов, которые строятся по похожему принципу — иконка над строкой текста. Столбец в этой строке равномерно заполняется и текст и иконки рисуются основным цветом, который выбран голубым в нашем проекте в методе build().

class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { //... return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), //...
}

Так как код построения каждого ряда будет практически идентичен, то наиболее эффективно будет использовать вложенную функцию, такую как buildButtonColumn(), которая включает в себя иконку и текст и возвращает столбец с этим виджетом.

class MyApp extends StatelessWidget //...
}

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

class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { //... Widget buttonSection = Container( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ buildButtonColumn(Icons.call, 'CALL'), buildButtonColumn(Icons.near_me, 'ROUTE'), buildButtonColumn(Icons.share, 'SHARE'), ], ), ); //...
}

Шаг 4: Построим секцию описания

Определим секцию описания, которая довольно длинная. Поместим текст в контейнер и добавим отступы 32 пикселя от каждого края.

class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { //... Widget textSection = Container( padding: const EdgeInsets.all(32.0), child: Text( '''
Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese Alps. Situated 1,578 meters above sea level, it is one of the larger Alpine Lakes. A gondola ride from Kandersteg, followed by a half-hour walk through pastures and pine forest, leads you to the lake, which warms to 20 degrees Celsius in the summer. Activities enjoyed here include rowing, and riding the summer toboggan run. ''', softWrap: true, ), ); //...
}

Шаг 5: Построим секцию с изображением

Три из четырех столбцов уже построены, осталось сделать только только столбец изображения. Изображение, которе используется в данном проекте находится доступно онлайн под лицензией «Creative Commons license». Но оно большое и загружаться оно будет медленно. В шаге 0 мы добавили изображение к нашему проекту и обновили конфигурационный файл, теперь добавим ссылку на него в своем коде.

return MaterialApp(
//...
body: ListView( children: [ Image.asset( 'images/lake.jpg', height: 240.0, fit: BoxFit.cover, ), // ... ],
),
//...
);

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

Шаг 6: Объединим все вместе

В финальном шаге соберем все кусочки нашего кода вместе. Виджет организован в ListView, а не Column потому ListView автоматически скроллится во время прокрутки на маленьком устройстве.

//...
return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: Text('Top Lakes'), ), body: ListView( children: [ Image.asset( 'images/lake.jpg', width: 600.0, height: 240.0, fit: BoxFit.cover, ), titleSection, buttonSection, textSection, ], ), ), );
//...

Теги
Показать больше

Похожие статьи

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

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

Кнопка «Наверх»
Закрыть