5/5 (2) Макеты во Flutter

В чем смысл?

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

Основой механизма разметки Flutter являются виджеты. Во Flutter почти все являются виджетами, даже модели макетов являются виджетами. Изображения, значки и текст, которые вы видите в приложении Flutter, являются виджетами. Но и те вещи, которые вы не видите, также являются виджетами, такими как строки, столбцы и сетки, которые упорядочивают, ограничивают и выравнивают видимые виджеты.

Вы создаете макет, составляя виджеты для создания более сложных виджетов. Например, на первом снимке экрана ниже показаны 3 значка с ярлыком под каждым из них:

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

[info] Примечание. Большинство скриншотов экрана в этом руководстве отображаются с параметром debugPaintSizeEnabled, установленным в значение true, чтобы вы могли видеть визуальный макет. Для получения дополнительной информации см. Debugging layout issues visually, раздел Using the Flutter inspector. [/info]

Вот схема дерева виджетов для этого интерфейса:

Большая часть этого должна выглядеть так, как на рисунке выше, но вам может быть интересно узнать о контейнерах (показаны розовым цветом). Container — это класс виджетов, который позволяет вам настроить его дочерний виджет. Используйте Container, если вы хотите добавить отступы, поля, границы или цвет фона.

В этом примере каждый текстовый виджет Text помещается в контейнер Container для добавления полей. Вся строка Row также помещается в контейнер Container, чтобы добавить отступы вокруг строки.

Макетирование виджета

Как разместить простой виджет во Flutter? В этом разделе показано, как создать и отобразить простой виджет. Он также показывает весь код для простого приложения Hello World.

В Flutter для вывода текста, значка или изображения на экран требуется всего несколько шагов.

1. Выбираем виджет макета

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

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

2. Создаем видимый виджет

Например, создание текстового виджета Text:

Text('Hello World'),

Создание виджета изображения Image :

Image.asset(
  'images/lake.jpg',
  fit: BoxFit.cover,
),

Создание виджета иконки Icon:

Icon(
  Icons.star,
  color: Colors.red[500],
),
3. Добавляем видимый виджет в виджет макета

Все виджеты макета имеют следующие положения:

  • Используется свойство child, если виджет имеет только один дочерний элемент – к примеру, Center или Container
  • Используется свойство children, если виджет имеет список дочерних элементов – к примеру, Row, Column, ListView, или Stack

Ниже показан пример добавление текстового виджета Text в виджет Center:

Center(
  child: Text('Hello World'),
),
4. Добавление виджетв макета на страницу

Приложение Flutter само по себе является виджетом, и большинство виджетов имеют метод build(). Создание и возврат виджета в методе приложения build() отображает виджет.

Приложение с Material Design

Для приложения Material вы можете использовать виджет Scaffold он предоставляет баннер по умолчанию с цветом фона и имеет API для добавления перекрывающей меню(drawers), полосы уведомлений(snack bars) и нижних вкладок(sheets). Затем вы можете добавить виджет Center непосредственно в свойство body домашней страницы.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter layout demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter layout demo'),
        ),
        body: Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}

[info]Примечание. В библиотеке Material library реализованы виджеты, соответствующие принципам Material Design. При разработке вашего пользовательского интерфейса вы можете использовать исключительно виджеты из стандартной библиотеки виджетов или использовать виджеты из Material library. Вы можете смешивать виджеты из обеих библиотек, вы можете настроить существующие виджеты или создать свой собственный набор пользовательских виджетов. [/info]

Приложение без Material Design

Для приложений, не относящихся к Material Design, вы можете добавить виджет Center в метод build() приложения:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(color: Colors.white),
      child: Center(
        child: Text(
          'Hello World',
          textDirection: TextDirection.ltr,
          style: TextStyle(
            fontSize: 32,
            color: Colors.black87,
          ),
        ),
      ),
    );
  }
}

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

Это оно! Когда вы запустите приложение, вы должны увидеть Hello World.


Размещение нескольких виджетов по вертикали и горизонтали

Одним из наиболее распространенных шаблонов макета является расположение виджетов по вертикали или горизонтали. Вы можете использовать виджет Row, чтобы расположить виджеты горизонтально, и виджет Column, чтобы расположить виджеты вертикально.

В чем смысл?

  • Row и Column — два наиболее часто используемых макета.
  • Row и Column принимают список дочерних виджетов.
  • Дочерний виджет может представлять собой опять таки Row, Column или другой сложный виджет.
  • Вы можете указать, как строка или столбец выравнивают свои дочерние элементы как по вертикали, так и по горизонтали.
  • Вы можете растягивать или ограничивать определенные дочерние виджеты.
  • Вы можете указать, как дочерние виджеты будут использовать доступное пространство строки или столбца.

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

Этот макет организован как строка Row. Строка содержит двух дочерних элементов: столбец Column слева и изображение Image — справа:

Дерево виджетов левого столбца содержит строки и столбцы.

Вы реализовываете часть кода компоновки десерта во вложенных строках и столбцах. Подробнее см. Nesting rows and columns.

[info]Примечание. Row и Column — это базовые примитивные виджеты для горизонтальной и вертикальной компоновки — эти низкоуровневые виджеты обеспечивают максимальную настройку. Flutter также предлагает специализированные высокоуровневые виджеты, которые могут быть достаточными для ваших нужд. Например, вместо строки вы можете предпочесть ListTile, простой в использовании виджет со свойствами для начальных и конечных значков и до 3 строк текста. Вместо Column вы можете предпочесть ListView, похожий на столбец — макет, который автоматически прокручивается, если его содержимое слишком длинное, чтобы соответствовать доступному пространству. Для получения дополнительной информации см. Common layout widgets.[/info]

Выравнивание виджетов

Вы контролируете процесс позиционирования, так как строка или столбец выравнивает свои дочерние элементы, используя свойства mainAxisAlignment и crossAxisAlignment. Для ряда главная ось проходит горизонтально, а поперечная ось проходит вертикально. Для столбца главная ось проходит вертикально, а поперечная ось проходит горизонтально

Классы MainAxisAlignment и CrossAxisAlignment предлагают различные константы для управления выравниванием.

[info]Примечание. При добавлении изображений в проект необходимо обновить файл pubspec для доступа к ним — в этом примере для отображения изображений используется Image.asset. Для получения дополнительной информации см. pubspec.yaml file, или Adding Assets and Images in Flutter. Вам не нужно делать это, если вы ссылаетесь на онлайн-изображения с помощью Image.network. [/info]

В следующем примере каждое из 3 изображений имеет ширину 100 пикселей. Поле рендеринга (в данном случае весь экран) имеет ширину более 300 пикселей, поэтому установка выравнивания по главной оси в spaceEvenly равномерно делит свободное горизонтальное пространство между, до и после каждого изображения.

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Image.asset('images/pic1.jpg'),
    Image.asset('images/pic2.jpg'),
    Image.asset('images/pic3.jpg'),
  ],
);

Исходники: row_column

Столбцы работают так же, как строки. В следующем примере показан столбец из 3 изображений, каждое из которых имеет высоту 100 пикселей. Высота поля рендеринга (в данном случае всего экрана) составляет более 300 пикселей, поэтому установка выравнивания по главной оси в spaceEvenly равномерно делит свободное вертикальное пространство между, над и под каждым изображением.

Column(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Image.asset('images/pic1.jpg'),
    Image.asset('images/pic2.jpg'),
    Image.asset('images/pic3.jpg'),
  ],
);

Исходники: row_column

Размеры виджетов

Если компоновка слишком велика для устройства, вдоль затронутого края появляется желто-черный полосатый рисунок. Вот пример слишком широкой строки:

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

Row(
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    Expanded(
      child: Image.asset('images/pic1.jpg'),
    ),
    Expanded(
      child: Image.asset('images/pic2.jpg'),
    ),
    Expanded(
      child: Image.asset('images/pic3.jpg'),
    ),
  ],
);

Исходники: sizing

Возможно, вы хотите, чтобы виджет занимал вдвое больше места, чем другие дочерние виджеты его же уровня. Для этого используйте свойство flex виджета Expanded, который принимает целое число, определяющий коэффициент гибкости для виджета. Коэффициент гибкости по умолчанию равен 1. Следующий код устанавливает коэффициент гибкости среднего изображения равным 2:

Row(
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    Expanded(
      child: Image.asset('images/pic1.jpg'),
    ),
    Expanded(
      flex: 2,
      child: Image.asset('images/pic2.jpg'),
    ),
    Expanded(
      child: Image.asset('images/pic3.jpg'),
    ),
  ],
);

Исходники: sizing

Упаковка виджетов

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

Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.black),
    Icon(Icons.star, color: Colors.black),
  ],
)

Исходники: pavlova

Вложенные строки и столбцы

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

Выделенный раздел реализован в виде двух строк. Строка рейтингов содержит пять звезд и количество отзывов. Ряд значков содержит три столбца значков и текста.

Дерево виджетов для строки рейтингов имеет следующий вид:

Переменная ratings создает строку, содержащую меньшую строку из 5 значков звездочек и текст:

var stars = Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.black),
    Icon(Icons.star, color: Colors.black),
  ],
);

final ratings = Container(
  padding: EdgeInsets.all(20),
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      stars,
      Text(
        '170 Reviews',
        style: TextStyle(
          color: Colors.black,
          fontWeight: FontWeight.w800,
          fontFamily: 'Roboto',
          letterSpacing: 0.5,
          fontSize: 20,
        ),
      ),
    ],
  ),
);

[info] Совет: Чтобы минимизировать визуальную путаницу, которая может возникнуть из-за сильно вложенного кода макета, реализуйте части пользовательского интерфейса в переменных и функциях.[/info]

Ряд значков под строкой оценок содержит 3 столбца; каждый столбец содержит значок и две строки текста, как вы можете видеть в его дереве виджетов:

Переменная iconList определяет строку значков:

final descTextStyle = TextStyle(
  color: Colors.black,
  fontWeight: FontWeight.w800,
  fontFamily: 'Roboto',
  letterSpacing: 0.5,
  fontSize: 18,
  height: 2,
);

// DefaultTextStyle.merge() allows you to create a default text
// style that is inherited by its child and all subsequent children.
final iconList = DefaultTextStyle.merge(
  style: descTextStyle,
  child: Container(
    padding: EdgeInsets.all(20),
    child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Column(
          children: [
            Icon(Icons.kitchen, color: Colors.green[500]),
            Text('PREP:'),
            Text('25 min'),
          ],
        ),
        Column(
          children: [
            Icon(Icons.timer, color: Colors.green[500]),
            Text('COOK:'),
            Text('1 hr'),
          ],
        ),
        Column(
          children: [
            Icon(Icons.restaurant, color: Colors.green[500]),
            Text('FEEDS:'),
            Text('4-6'),
          ],
        ),
      ],
    ),
  ),
);

Переменная leftColumn содержит строки оценок и значков, а также заголовок и текст, описывающий дессерт:

final leftColumn = Container(
  padding: EdgeInsets.fromLTRB(20, 30, 20, 20),
  child: Column(
    children: [
      titleText,
      subTitle,
      ratings,
      iconList,
    ],
  ),
);

Левый столбец помещается в контейнер Container, чтобы ограничить его ширину. Наконец, пользовательский интерфейс создается со всей строкой (содержащей левый столбец и изображение) внутри карты Card.

Изображение дессерта из Pixabay. Вы можете встроить изображение из сети с помощью Image.network(), но, для этого примера, изображение сохраняется в каталоге изображений в проекте, добавляется в файл pubspec и доступно с помощью Images.asset(). Для получения дополнительной информации см. Adding assets and images.

body: Center(
  child: Container(
    margin: EdgeInsets.fromLTRB(0, 40, 0, 30),
    height: 600,
    child: Card(
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            width: 440,
            child: leftColumn,
          ),
          mainImage,
        ],
      ),
    ),
  ),
),

[info]Подсказка: пример дессерта лучше всего работает горизонтально на широком устройстве, например на планшете. Если вы используете этот пример в симуляторе iOS, вы можете выбрать другое устройство, используя меню Hardware > Device. Для этого примера мы рекомендуем iPad Pro. Вы можете изменить его ориентацию на альбомный режим, используя Hardware > Rotate. Вы также можете изменить размер окна симулятора (без изменения количества логических пикселей), используя Window> Scale.[/info]

Исходники: дессерт(pavlova)


Общие макеты виджетов

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

Следующие виджеты делятся на две категории: стандартные виджеты из библиотеки виджетов и специализированные виджеты из библиотеки Material Design. Любое приложение может использовать библиотеку виджетов, но только приложения с Material Design могут использовать библиотеку Material Components.

Стандартные виджеты

  • Container: Добавляет к виджету отступы, поля, границы, цвет фона или другие элементы оформления.
  • GridView: Размещает виджеты в виде прокручиваемой сетки.
  • ListView: Размещает виджеты в виде прокручиваемого списка.
  • Stack: Перекрывает виджет поверх другого.

Material виджеты

  • Card: Упорядочивает связанную информацию в поле с закругленными углами и тенью.
  • ListTile: Упорядочивает до 3 строк текста и дополнительных начальных и конечных значков в ряд.

Виджет Container

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

Резюме (Контейнер)
  • Добавить отступы, поля, границы
  • Изменить цвет фона или изображение
  • Содержит один дочерний виджет, но этот дочерний элемент может быть строкой, столбцом или даже корнем дерева виджета.

Примеры (Контейнер)

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

Widget _buildImageColumn() => Container(
      decoration: BoxDecoration(
        color: Colors.black26,
      ),
      child: Column(
        children: [
          _buildImageRow(1),
          _buildImageRow(3),
        ],
      ),
    );

Контейнер Container также используется для добавления округленной границы и полей к каждому изображению:

Widget _buildDecoratedImage(int imageIndex) => Expanded(
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(width: 10, color: Colors.black38),
          borderRadius: const BorderRadius.all(const Radius.circular(8)),
        ),
        margin: const EdgeInsets.all(4),
        child: Image.asset('images/pic$imageIndex.jpg'),
      ),
    );

Widget _buildImageRow(int imageIndex) => Row(
      children: [
        _buildDecoratedImage(imageIndex),
        _buildDecoratedImage(imageIndex + 1),
      ],
    );

Вы можете найти больше примеров контейнеров в учебнике tutorial и в галерее Flutter Gallery.

Исходники: container


Виджет GridView

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

Резюме (GridView)
  • Размещает виджеты в сетке
  • Определяет, когда содержимое столбца превышает поле рендеринга, и автоматически обеспечивает прокрутку
  • Создайте свою собственную пользовательскую сетку или используйте одну из предоставленных сеток:
    • GridView.count позволяет указать количество столбцов
    • GridView.extent позволяет указать максимальную ширину пикселя плитки

[info] Примечание. При отображении двумерного списка, в котором важно, какую строку и столбец занимает ячейка (например, это запись в столбце «калории» для строки «авокадо»), используйте Table или DataTable. [/info]

Примеры (GridView)

Использует GridView.extent для создания сетки с плитками шириной не более 150 пикселей.

Исходники: grid_and_list

Использует GridView.count для создания сетки шириной 2 плитки в портретном режиме и шириной 3 плитки в ландшафтном режиме. Заголовки создаются путем установки свойства нижнего footer для каждого GridTile.

Исходники: grid_list_demo.dart из Flutter Gallery

Widget _buildGrid() => GridView.extent(
    maxCrossAxisExtent: 150,
    padding: const EdgeInsets.all(4),
    mainAxisSpacing: 4,
    crossAxisSpacing: 4,
    children: _buildGridTileList(30));

// The images are saved with names pic0.jpg, pic1.jpg...pic29.jpg.
// The List.generate() constructor allows an easy way to create
// a list when objects have a predictable naming pattern.
List _buildGridTileList(int count) => List.generate(
    count, (i) => Container(child: Image.asset('images/pic$i.jpg')));

Виджет ListView

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

Резюме (ListView)
  • Специализированная колонка Column для организации списка ящечков
  • Можно выложить горизонтально или вертикально
  • Определяет, когда его содержимое не подходит, и обеспечивает прокрутку
  • Менее настраиваемый, чем колонка Column, но проще в использовании и поддерживает прокрутку

Примеры (ListView)

Использует ListView для отображения списка предприятий, использующих ListTiles. Разделитель Divider отделяет театры от ресторанов.

Исходники: grid_and_list

Использует ListView для отображения цветов Colors из палитры Material Design для определенного семейства цветов.

Исходники: colors_demo.dart из Flutter Gallery

Widget _buildList() => ListView(
      children: [
        _tile('CineArts at the Empire', '85 W Portal Ave', Icons.theaters),
        _tile('The Castro Theater', '429 Castro St', Icons.theaters),
        _tile('Alamo Drafthouse Cinema', '2550 Mission St', Icons.theaters),
        _tile('Roxie Theater', '3117 16th St', Icons.theaters),
        _tile('United Artists Stonestown Twin', '501 Buckingham Way',
            Icons.theaters),
        _tile('AMC Metreon 16', '135 4th St #3000', Icons.theaters),
        Divider(),
        _tile('Kescaped_code#39;s Kitchen', '757 Monterey Blvd', Icons.restaurant),
        _tile('Emmyescaped_code#39;s Restaurant', '1923 Ocean Ave', Icons.restaurant),
        _tile(
            'Chaiya Thai Restaurant', '272 Claremont Blvd', Icons.restaurant),
        _tile('La Ciccia', '291 30th St', Icons.restaurant),
      ],
    );

ListTile _tile(String title, String subtitle, IconData icon) => ListTile(
      title: Text(title,
          style: TextStyle(
            fontWeight: FontWeight.w500,
            fontSize: 20,
          )),
      subtitle: Text(subtitle),
      leading: Icon(
        icon,
        color: Colors.blue[500],
      ),
    );

Виджет Stack

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

Резюме (Stack)
  • Используйте для виджетов, которые перекрывают другой виджет
  • Первый виджет в списке детей является базовым виджетом; последующие дети накладываются поверх этого базового виджета
  • Содержимое стека Stack не может прокручиваться
  • Вы можете обрезать потомков, которые превышают поле рендеринга

Примеры (Stack)

Использование стека Stack для наложения контейнера Container (текст Text которого отображается на полупрозрачном черном фоне) поверх CircleAvatar. Стек компенсирует текст, используя свойство выравнивания alignment и выравнивания Alignment.

Исходники: card_and_stack

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

Исходники: contacts_demo.dart из Flutter Gallery

Widget _buildStack() => Stack(
    alignment: const Alignment(0.6, 0.6),
    children: [
      CircleAvatar(
        backgroundImage: AssetImage('images/pic.jpg'),
        radius: 100,
      ),
      Container(
        decoration: BoxDecoration(
          color: Colors.black45,
        ),
        child: Text(
          'Mia B',
          style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
            color: Colors.white,
          ),
        ),
      ),
    ],
  );

Виджет Card

Карта Card из библиотеки материалов Material library содержит связанные фрагменты информации и может быть составлена практически из любого виджета, но часто используется с ListTile. У Card есть один дочерний элемент, но его дочерним элементом может быть столбец, строка, список, сетка или другой виджет, поддерживающий несколько дочерних элементов. По умолчанию размер карты уменьшается до 0 на 0 пикселей. Вы можете использовать SizedBox, чтобы ограничить размер карты.

В Flutter карта Card имеет слегка закругленные углы и тень, что придает ей эффект 3D. Изменение свойства высоты elevation карты позволяет управлять эффектом тени. Например, установка свойства elevation на 24 визуально поднимает карту Card дальше от поверхности и вызывает более рассеянную тень. Для получения списка поддерживаемых значений высот см. Elevation в Material guidelines. Указание неподдерживаемого значения полностью отключает тень.

Резюме (Card)
  • Реализует карточку Material card .
  • Используется для представления связанных слепков информации.
  • Принимает одного дочернего элемента, но этим дочерним элементом может быть виджет Row, Column или другой элемент, содержащий список дочерних элементов.
  • Отображается с закругленными углами и тенью.
  • Содержимое карты не может прокручиваться
  • Используется из Material library

Примеры (Card)

Карта Card, содержащая 3 ListTiles и размером, оборачивает ее SizedBox. Разделитель Divider разделяет первый и второй ListTiles.

Исходники: card_and_stack

Карточка Card , содержащая изображение и текст.

Исходники: cards_demo.dart из Flutter Gallery

Widget _buildCard() => SizedBox(
    height: 210,
    child: Card(
      child: Column(
        children: [
          ListTile(
            title: Text('1625 Main Street',
                style: TextStyle(fontWeight: FontWeight.w500)),
            subtitle: Text('My City, CA 99984'),
            leading: Icon(
              Icons.restaurant_menu,
              color: Colors.blue[500],
            ),
          ),
          Divider(),
          ListTile(
            title: Text('(408) 555-1212',
                style: TextStyle(fontWeight: FontWeight.w500)),
            leading: Icon(
              Icons.contact_phone,
              color: Colors.blue[500],
            ),
          ),
          ListTile(
            title: Text('costa@example.com'),
            leading: Icon(
              Icons.contact_mail,
              color: Colors.blue[500],
            ),
          ),
        ],
      ),
    ),
  );

Виджет ListTile

Используйте ListTile, специализированный виджет строки из библиотеки Material library , чтобы упростить создание строки, содержащей до 3 строк текста и необязательных начальных и конечных значков. ListTile чаще всего используется в Card или ListView , но может использоваться в другом месте.

Резюме (ListTile)
  • Специализированная строка, содержащая до 3 строк текста и дополнительные значки
  • Менее настраиваемый, чем Row, но проще в использовании
  • Из библиотеки Material library

Примеры (ListTile)

Карта Card, содержащая 3 ListTiles.

Исходники: card_and_stack

Использует ListTile, чтобы перечислить 3 типа выпадающих кнопок.

Исходники: buttons_demo.dart из Flutter Gallery

Для данного материала был использован официальный источник Layouts in Flutter

Пожалуйста, оцените материал

WebSofter

Web - технологии