Flutter Widgets — основни градивни блокови корисничког интерфејса у Google Flutter оквиру, објављеном у стабилној верзији 1.0 у децембру 2018. године. У Flutter-у све је виџет: од екрана и дугмета до размака и поравнања. Виџети формирају стабло (widget tree) које Flutter рендерује на сопствени погон Skia/Impeller, заобилазећи native компоненте платформе. Према 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 не користи native компоненте — све се црта погоном 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 се користи за интерактивне елементе: бројаче, текстуална поља, checkbox-ове, анимације, тајмере.
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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође