Flutter Widgets — базовые строительные блоки пользовательского интерфейса во фреймворке Google Flutter, выпущенном в стабильной версии 1.0 в декабре 2018 года. В Flutter всё — виджет: от экрана и кнопки до отступа и выравнивания. Виджеты образуют дерево (widget tree), которое Flutter рендерит на собственный движок Skia/Impeller, минуя нативные компоненты платформы. По данным Google I/O (2025), Flutter используется более чем в 500 000 приложений в Google Play и App Store. Архитектура Flutter разделяет виджеты на StatelessWidget (неизменяемые) и StatefulWidget (с изменяемым состоянием через State-объект).
Главное
Flutter Widgets — все элементы UI во фреймворке Flutter, реализованные как неизменяемые (immutable) Dart-классы. Виджет — это конфигурация элемента UI: его размер, цвет, положение, обработчики событий. В отличие от Android (XML + View) или iOS (Storyboard + UIView), Flutter не использует нативные компоненты — всё рисуется движком Skia (Android/iOS/Linux) или Impeller (iOS/macOS) на Canvas. Это обеспечивает одинаковый внешний вид на всех платформах без платформенных расхождений. Flutter поставляется с двумя наборами виджетов: Material Widgets (дизайн Google Material Design 3 для Android/веба) и Cupertino Widgets (дизайн Apple HIG для iOS/macOS). Разработчик может комбинировать оба набора в одном приложении. Каждый виджет имеет метод build(), возвращающий дочерний виджет или их композицию — так строится дерево виджетов.
Flutter оперирует тремя деревьями: Widget Tree (конфигурация, создаётся разработчиком), Element Tree (сопоставление виджета с позицией в дереве, управляется фреймворком), Render Tree (объекты, вычисляющие layout и выполняющие paint). Widget создаёт Element, который создаёт RenderObject. Element переиспользуется при изменении конфигурации (rebuild) — это механизм оптимизации Flutter: если тип виджета и key совпадают, Element не пересоздаётся, а обновляется новая конфигурация. Понимание трёх деревьев — ключ к оптимизации производительности Flutter-приложений.
StatelessWidget — виджет, который не хранит внутреннее состояние. Он принимает параметры через конструктор и отображает их без возможности изменения после сборки. StatelessWidget идеально подходит для статических элементов: заголовков, иконок, аватаров, списков с фиксированными данными. Метод build() вызывается один раз при создании и при изменении родительского виджета. Поскольку StatelessWidget не имеет состояния, он не требует отдельного State-объекта — build() определён прямо в классе виджета.
import 'package:flutter/material.dart';
class ProfileHeader extends StatelessWidget {
final String name;
final String avatarUrl;
const ProfileHeader({super.key, required this.name, required this.avatarUrl});
@override
Widget build(BuildContext context) {
return Row(
children: [
CircleAvatar(
radius: 24,
backgroundImage: NetworkImage(avatarUrl),
),
const SizedBox(width: 12),
Text(
name,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
);
}
}ProfileHeader — StatelessWidget, принимающий name и avatarUrl через конструктор. CircleAvatar отображает аватар, Text — имя. Виджет не может изменить эти значения после создания. Использование const конструктора (const ProfileHeader) позволяет Flutter переиспользовать экземпляр виджета при rebuild родителя — это микрооптимизация, рекомендованная для всех StatelessWidget.
StatefulWidget — виджет с изменяемым состоянием, которое хранится в отдельном объекте State. Сам StatefulWidget — неизменяемый (immutable), как и StatelessWidget. Изменяемая часть вынесена в State: State — объект, который создаётся один раз и переживает множественные ребилды виджета. Когда состояние меняется (setState()), Flutter вызывает build() State, обновляя UI. StatefulWidget используется для интерактивных элементов: счётчики, текстовые поля, чекбоксы, анимации, таймеры.
import 'package:flutter/material.dart';
class LikeButton extends StatefulWidget {
const LikeButton({super.key});
@override
State<LikeButton> createState() => _LikeButtonState();
}
class _LikeButtonState extends State<LikeButton> {
bool liked = false;
int count = 42;
void _toggleLike() {
setState(() {
liked = !liked;
count += liked ? 1 : -1;
});
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _toggleLike,
child: Text(liked ? '♥ $count' : '♡ $count'),
);
}
}LikeButton — StatefulWidget с State-классом _LikeButtonState. Поля liked и count — состояние, которое хранится в State и не сбрасывается при rebuild. setState() уведомляет Flutter о необходимости перестроить UI. Flutter не воссоздаёт State при каждом родительском rebuild — только при изменении конфигурации (key или тип виджета). В IT Sectr мы используем StatelessWidget для отображения и StatefulWidget для интерактивных компонентов, следуя принципу минимизации StatefulWidget до границ мутации.
Widget Tree — иерархическая структура виджетов, описывающая UI приложения. Flutter преобразует Widget Tree в Element Tree: каждый Widget создаёт Element, который отслеживает позицию в дереве и связь с RenderObject. Render Tree выполняет layout (определение размеров и позиций) и paint (отрисовку). Element — ключевой оптимизационный слой: если тип виджета и key не изменились при rebuild, Element переиспользуется, обновляя конфигурацию без пересоздания RenderObject. Это обеспечивает производительность Flutter при высокой частоте кадров (60/120 FPS).
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Flutter Widgets')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.flutter_dash, size: 80),
const SizedBox(height: 16),
const Text(
'Hello, Flutter!',
style: TextStyle(fontSize: 24),
),
],
),
),
);
}
}Дерево виджетов HomeScreen: Scaffold → AppBar + Center → Column → [Icon, SizedBox, Text]. Scaffold — корневой layout-виджет Material Design. Center центрирует дочерний Column. Column располагает детей вертикально с выравниванием по центру (mainAxisAlignment.center). Flutter вычисляет layout сверху вниз (constraints передаются от родителя), а размеры — снизу вверх (sizedByParent или sizing from children).
BuildContext — дескриптор позиции виджета в Element Tree. Каждый метод build() получает BuildContext, через который виджет может получить доступ к:MediaQuery (размер экрана, ориентация, плотность пикселей, safe area), Theme (MaterialThemeData или CupertinoThemeData), Navigator (навигационный стек), ScaffoldMessenger (SnackBar), InheritedWidget (прокидывание данных вниз по дереву). BuildContext не должен сохраняться после завершения build() или использоваться вне синхронного контекста — это приводит к ошибкам «Scaffold.of() called with a context that does not contain a Scaffold». Вместо сохранения context используйте Builder-виджет или паттерн InheritedWidget для доступа к данным.
Key — опциональный параметр конструктора каждого виджета (super.key). Key помогает Flutter идентифицировать виджет при изменении порядка/количества элементов в списке. Без key Flutter сравнивает виджеты по типу и позиции; при добавлении элемента в середину списка без key Flutter переиспользует Element для неправильного виджета, вызывая баги с состоянием (StatefulWidget) и анимацией. Используйте ValueKey (уникальный идентификатор) для списков, ObjectKey (на основе объекта данных), UniqueKey (гарантированно уникальный при каждом rebuild — для форсированного пересоздания).
Flutter SDK (стабильная версия 3.3+, Dart 3+) включает 200+ встроенных виджетов, разделённых на категории: Layout (Row, Column, Stack, Container, Expanded, Flexible, Wrap, GridView, ListView, CustomScrollView), Material Design (Scaffold, AppBar, Card, Drawer, BottomNavigationBar, FloatingActionButton, TabBar, Chip, DataTable), Cupertino (CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton, CupertinoTabBar), Painting & Effects (Opacity, DecoratedBox, ClipRect, Transform, BackdropFilter, ShaderMask), Async (FutureBuilder, StreamBuilder) и Accessibility (Semantics, MergeSemantics, ExcludeSemantics). Layout-виджеты — основа любого Flutter UI: Row для горизонтальных последовательностей, Column для вертикальных, Stack для перекрывающихся элементов, Container с BoxDecoration для декорирования.
| Категория | Ключевые виджеты | Назначение |
|---|---|---|
| Layout | Row, Column, Stack, Container, Expanded, Flexible | Позиционирование и размеры дочерних элементов |
| Material | Scaffold, AppBar, Card, Drawer, FAB, TabBar | UI-компоненты Material Design 3 |
| Cupertino | CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton | iOS-стилизованные компоненты |
| Painting | Opacity, ClipRect, Transform, DecoratedBox, BackdropFilter | Визуальные эффекты и клиппинг |
| Async | FutureBuilder, StreamBuilder | Асинхронная загрузка данных с UI-состояниями |
| Accessibility | Semantics, MergeSemantics | Семантическая разметка для screen readers |
Часто задаваемые вопросы
StatelessWidget не имеет внутреннего состояния — все данные передаются через конструктор и не меняются. StatefulWidget хранит изменяемое состояние в отдельном объекте State, который переживает ребилды. Изменение состояния вызывает setState(), и Flutter перестраивает UI. Для неизменяемых элементов используйте StatelessWidget; для интерактивных — StatefulWidget.
BuildContext — дескриптор позиции виджета в Element Tree, передаваемый в метод build(). Через context виджет получает доступ к MediaQuery, Theme, Navigator, ScaffoldMessenger и InheritedWidget. BuildContext не должен сохраняться после завершения build(). Для доступа к данным используйте Builder-виджет или InheritedWidget.
Да, Flutter использует Dart как единственный язык программирования. Dart — статически типизированный язык с null-safety, звуковыми типами (sound null safety), extension methods и pattern matching. Для начала достаточно основ Dart: классы, функции, async/await, коллекции. Dart компилируется в нативный код (AOT) через Dart Native и в JavaScript (для веба) через Dart2JS.
Нет, Flutter поддерживает шесть платформ: iOS, Android, Web, macOS, Windows, Linux. Более 90% кода общее для всех платформ. Платформенные адаптации (камера, файловая система) реализуются через плагины или platform channels. Для десктопа Flutter использует оконную оболочку Flutter Desktop, для веба — движок CanvasKit (WebGL) или HTML-рендерер.
Flutter достигает 60/120 FPS за счёт: собственного 2D-движка (Skia/Impeller), отсутствия нативного bridge (в отличие от React Native), трёх деревьев (Widget → Element → Render) с переиспользованием Element при неизменном типе/key, layout-алгоритма с однонаправленным проходом (constraints down, sizes up) и RepaintBoundary для изоляции перерисовки отдельных зон экрана.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также