Виджеты
дерево, композиция и почему отступ — это тоже виджет
Что это
Во Flutter всё — виджет. Кнопка, текст, отступ, выравнивание, даже сам экран. Интерфейс собирается не из свойств, как в CSS, а из вложенных друг в друга виджетов.
Это главное отличие от всего, что было в книге раньше, и главный источник недоумения при чтении: код выглядит как глубокая лестница скобок.
Как выглядит в коде
Scaffold(
appBar: AppBar(title: const Text('Погода')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(city.name, style: Theme.of(context).textTheme.titleLarge),
const SizedBox(height: 8),
Text(city.temp == null ? 'нет данных' : '${city.temp}°'),
const Spacer(),
ElevatedButton(
onPressed: () => onRemove(city.name),
child: const Text('Удалить'),
),
],
),
),
)Как это читать
Читай по вложенности, а не по строкам. Отступы в коде повторяют структуру дерева, поэтому самое полезное при чтении — смотреть на уровень отступа.
child — один ребёнок, children — список. По этим двум словам
восстанавливается вся структура: где ветвление, где цепочка.
Отступы и промежутки — тоже виджеты. В этом главное отличие от CSS:
| Нужно | Виджет |
|---|---|
| отступ вокруг | Padding |
| промежуток между | SizedBox(height: 8) |
| занять всё свободное | Expanded, Spacer |
| выровнять | Align, Center |
| в столбец / в ряд | Column, Row |
| поверх друг друга | Stack |
Поэтому дерево такое глубокое: то, что в CSS было бы двумя строками свойств, здесь — два уровня вложенности.
const перед виджетом. Не формальность: такой виджет создаётся один раз
и не пересоздаётся при перерисовке. ИИ его часто пропускает, анализатор на это
ругается.
Theme.of(context) — взять значение из темы приложения: цвет, шрифт,
размер. Это аналог CSS-переменных (статья 8.3): лучше, чем вписывать размеры
числами.
Row, Column и переполнение
Самая частая визуальная поломка во Flutter: содержимое не помещается, и на экране появляется жёлто-чёрная полоса с надписью о переполнении.
Причина почти всегда одна: в Row положили текст, который длиннее экрана.
Лечится оборачиванием в Expanded или Flexible — они говорят «занимай
место, которое есть, и не больше».
Как сказать ИИ
Объясни это дерево виджетов: что за что отвечает.
По строке на уровень вложенности, без кода.Вынеси содержимое Column в отдельный виджет CityInfo
в lib/widgets/. Параметры передай через конструктор.
Поведение не меняй.При длинном названии города в этом Row случается overflow.
Исправь через Expanded, и объясни, почему именно так,
а не фиксированной шириной.На что смотреть
Дерево на десять уровней в одном файле. Разбивается на виджеты.
Нет const там, где виджет не зависит от данных. Лишние пересоздания при
каждой перерисовке.
Размеры числами вместо темы. fontSize: 17 вместо Theme.of(context) —
те же магические числа, что в статье 8.3.
Container ради одной вещи. Если нужен только отступ — Padding, только
выравнивание — Align. Container умеет всё сразу и потому прячет намерение.
Логика внутри build. Запросы к сети и вычисления в методе построения:
он вызывается при каждой перерисовке, то есть часто.
Фиксированные размеры под один экран. Телефоны разные; MediaQuery и
Expanded существуют именно для этого.
Шпаргалка
Во Flutter всё виджет, включая отступы и промежутки.
child— один,children— список; по ним восстанавливается дерево.Читай по вложенности, а не по строкам.
constперед виджетом экономит пересоздание при перерисовке.Размеры и цвета — из темы, а не числами.
Жёлто-чёрная полоса — переполнение; лечится
Expanded.