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/Web) и 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 — обект, който се създава веднъж и оцелява след множество rebuild-ове на уиджета. Когато състоянието се промени (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(
'Здравей, 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 (размер на екрана, ориентация, плътност на пикселите, безопасна зона), 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 | Семантично маркиране за екранни четци |
Често задавани въпроси
StatelessWidget няма вътрешно състояние — всички данни се предават чрез конструктора и не се променят. StatefulWidget съхранява променливото състояние в отделен State обект, който оцелява след rebuild-ове. Промяната на състоянието извиква 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), липсата на native bridge (за разлика от React Native), трите дървета (Widget → Element → Render) с повторно използване на Element при непроменен тип/key, алгоритъма за layout с еднопосочно преминаване (constraints down, sizes up) и RepaintBoundary за изолиране на прерисуването на отделни зони на екрана.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също