Flutter Widgets — τα βασικά δομικά στοιχεία της διεπαφής χρήστη στο πλαίσιο Google Flutter, που κυκλοφόρησε σε σταθερή έκδοση 1.0 τον Δεκέμβριο του 2018. Στο Flutter, τα πάντα είναι ένα widget: από την οθόνη και το κουμπί μέχρι το διάστημα και τη στοίχιση. Τα widgets σχηματίζουν ένα δέντρο (widget tree) το οποίο το Flutter αποδίδει στη δική του μηχανή Skia/Impeller, παρακάμπτοντας τα native στοιχεία της πλατφόρμας. Σύμφωνα με το Google I/O (2025), το Flutter χρησιμοποιείται σε περισσότερες από 500.000 εφαρμογές στο Google Play και το App Store. Η αρχιτεκτονική του Flutter χωρίζει τα widgets σε StatelessWidget (αμετάβλητα) και StatefulWidget (με μεταβλητή κατάσταση μέσω αντικειμένου State).
Κύρια Σημεία
Flutter Widgets — όλα τα στοιχεία UI στο πλαίσιο Flutter, υλοποιημένα ως αμετάβλητες (immutable) κλάσεις Dart. Ένα widget είναι μια διαμόρφωση ενός στοιχείου UI: το μέγεθος, το χρώμα, η θέση, ο χειρισμός γεγονότων. Σε αντίθεση με το Android (XML + View) ή το iOS (Storyboard + UIView), το Flutter δεν χρησιμοποιεί native στοιχεία — τα πάντα σχεδιάζονται από τη μηχανή Skia (Android/iOS/Linux) ή Impeller (iOS/macOS) στο Canvas. Αυτό εξασφαλίζει πανομοιότυπη εμφάνιση σε όλες τις πλατφόρμες χωρίς διαφορές πλατφόρμας. Το Flutter συνοδεύεται από δύο σύνολα widgets: Material Widgets (σχεδιασμός Google Material Design 3 για Android/Web) και Cupertino Widgets (σχεδιασμός Apple HIG για iOS/macOS). Ο προγραμματιστής μπορεί να συνδυάσει και τα δύο σύνολα σε μία εφαρμογή. Κάθε widget έχει μια μέθοδο build() που επιστρέφει ένα θυγατρικό widget ή μια σύνθεση αυτών — έτσι χτίζεται το δέντρο widgets.
Το Flutter λειτουργεί με τρία δέντρα: Widget Tree (διαμόρφωση, δημιουργείται από τον προγραμματιστή), Element Tree (αντιστοίχιση widget με θέση στο δέντρο, διαχειρίζεται από το πλαίσιο), Render Tree (αντικείμενα που υπολογίζουν τη διάταξη και εκτελούν τη σχεδίαση). Το Widget δημιουργεί το Element, το οποίο δημιουργεί το RenderObject. Το Element επαναχρησιμοποιείται κατά την αλλαγή διαμόρφωσης (rebuild) — αυτός είναι ο μηχανισμός βελτιστοποίησης του Flutter: αν ο τύπος widget και το key συμπίπτουν, το Element δεν δημιουργείται εκ νέου, αλλά ενημερώνεται η νέα διαμόρφωση. Η κατανόηση των τριών δέντρων είναι το κλειδί για τη βελτιστοποίηση της απόδοσης των εφαρμογών Flutter.
StatelessWidget — ένα widget που δεν αποθηκεύει εσωτερική κατάσταση. Δέχεται παραμέτρους μέσω κατασκευαστή και τις εμφανίζει χωρίς δυνατότητα αλλαγής μετά τη δημιουργία. Το StatelessWidget είναι ιδανικό για στατικά στοιχεία: επικεφαλίδες, εικονίδια, avatar, λίστες με σταθερά δεδομένα. Η μέθοδος build() καλείται μία φορά κατά τη δημιουργία και κατά την αλλαγή του γονικού widget. Επειδή το StatelessWidget δεν έχει κατάσταση, δεν απαιτεί ξεχωριστό αντικείμενο State — η build() ορίζεται απευθείας στην κλάση widget.
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 εμφανίζει το avatar, το Text το όνομα. Το widget δεν μπορεί να αλλάξει αυτές τις τιμές μετά τη δημιουργία. Η χρήση του κατασκευαστή const (const ProfileHeader) επιτρέπει στο Flutter να επαναχρησιμοποιήσει την παρουσία του widget κατά το rebuild του γονέα — αυτή είναι μια μικροβελτιστοποίηση που συνιστάται για όλα τα StatelessWidget.
StatefulWidget — ένα widget με μεταβλητή κατάσταση, αποθηκευμένη σε ξεχωριστό αντικείμενο State. Το ίδιο το StatefulWidget είναι αμετάβλητο (immutable), όπως και το StatelessWidget. Το μεταβλητό μέρος είναι απομονωμένο στο State: State — ένα αντικείμενο που δημιουργείται μία φορά και επιβιώνει από πολλαπλά rebuild του widget. Όταν η κατάσταση αλλάζει (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 ή τύπος widget). Στην IT Sectr χρησιμοποιούμε StatelessWidget για εμφάνιση και StatefulWidget για διαδραστικά στοιχεία, ακολουθώντας την αρχή ελαχιστοποίησης του StatefulWidget μέχρι τα όρια μετάλλαξης.
Widget Tree — η ιεραρχική δομή των widgets που περιγράφει το UI της εφαρμογής. Το Flutter μετατρέπει το Widget Tree σε Element Tree: κάθε Widget δημιουργεί ένα Element που παρακολουθεί τη θέση στο δέντρο και τη σύνδεση με το RenderObject. Το Render Tree εκτελεί διάταξη (προσδιορισμός μεγεθών και θέσεων) και σχεδίαση (paint). Το Element είναι το βασικό στρώμα βελτιστοποίησης: αν ο τύπος widget και το 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),
),
],
),
),
);
}
}Το δέντρο widgets του HomeScreen: Scaffold → AppBar + Center → Column → [Icon, SizedBox, Text]. Scaffold — το κύριο widget διάταξης του Material Design. Το Center κεντράρει το θυγατρικό Column. Το Column τακτοποιεί τα παιδιά κάθετα με κεντρική στοίχιση (mainAxisAlignment.center). Το Flutter υπολογίζει τη διάταξη από πάνω προς τα κάτω (οι περιορισμοί μεταβιβάζονται από τον γονέα) και τα μεγέθη από κάτω προς τα πάνω (sizedByParent ή sizing from children).
BuildContext — ένας περιγραφέας της θέσης του widget στο Element Tree. Κάθε μέθοδος build() λαμβάνει ένα BuildContext, μέσω του οποίου το widget μπορεί να έχει πρόσβαση σε:MediaQuery (μέγεθος οθόνης, προσανατολισμός, πυκνότητα pixel, ασφαλής περιοχή), Theme (MaterialThemeData ή CupertinoThemeData), Navigator (στοίβα πλοήγησης), ScaffoldMessenger (SnackBar), InheritedWidget (μεταβίβαση δεδομένων προς τα κάτω στο δέντρο). Το BuildContext δεν πρέπει να αποθηκεύεται μετά την ολοκλήρωση της build() ή να χρησιμοποιείται εκτός σύγχρονου περιβάλλοντος — αυτό οδηγεί σε σφάλματα όπως «Scaffold.of() called with a context that does not contain a Scaffold». Αντί να αποθηκεύετε το context, χρησιμοποιήστε το widget Builder ή το μοτίβο InheritedWidget για πρόσβαση σε δεδομένα.
Key — μια προαιρετική παράμετρος του κατασκευαστή κάθε widget (super.key). Το Key βοηθά το Flutter να αναγνωρίζει το widget κατά την αλλαγή σειράς/αριθμού στοιχείων σε μια λίστα. Χωρίς key, το Flutter συγκρίνει τα widgets κατά τύπο και θέση; κατά την προσθήκη στοιχείου στη μέση της λίστας χωρίς key, το Flutter επαναχρησιμοποιεί το Element για λάθος widget, προκαλώντας σφάλματα κατάστασης (StatefulWidget) και κινούμενων σχεδίων. Χρησιμοποιήστε ValueKey (μοναδικό αναγνωριστικό) για λίστες, ObjectKey (βάσει αντικειμένου δεδομένων), UniqueKey (εγγυημένα μοναδικό σε κάθε rebuild — για εξαναγκασμένη αναδημιουργία).
Το Flutter SDK (σταθερή έκδοση 3.3+, Dart 3+) περιλαμβάνει 200+ ενσωματωμένα widgets, χωρισμένα σε κατηγορίες: 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 widgets είναι η βάση κάθε Flutter UI: Row για οριζόντιες ακολουθίες, Column για κάθετες, Stack για επικαλυπτόμενα στοιχεία, Container με BoxDecoration για διακόσμηση.
| Κατηγορία | Βασικά widgets | Σκοπός |
|---|---|---|
| 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 — ένας περιγραφέας της θέσης του widget στο Element Tree, που μεταβιβάζεται στη μέθοδο build(). Μέσω του context, το widget έχει πρόσβαση σε MediaQuery, Theme, Navigator, ScaffoldMessenger και InheritedWidget. Το BuildContext δεν πρέπει να αποθηκεύεται μετά την ολοκλήρωση της build(). Για πρόσβαση σε δεδομένα χρησιμοποιήστε το widget Builder ή το InheritedWidget.
Ναι, το Flutter χρησιμοποιεί Dart ως μοναδική γλώσσα προγραμματισμού. Η Dart είναι μια στατικά τυποποιημένη γλώσσα με null-safety, sound types, extension methods και pattern matching. Για να ξεκινήσετε, αρκούν τα βασικά της Dart: κλάσεις, συναρτήσεις, async/await, συλλογές. Η Dart μεταγλωττίζεται σε native κώδικα (AOT) μέσω Dart Native και σε JavaScript (για web) μέσω Dart2JS.
Όχι, το Flutter υποστηρίζει έξι πλατφόρμες: iOS, Android, Web, macOS, Windows, Linux. Πάνω από το 90% του κώδικα είναι κοινό για όλες τις πλατφόρμες. Οι προσαρμογές πλατφόρμας (κάμερα, σύστημα αρχείων) πραγματοποιούνται μέσω πρόσθετων ή platform channels. Για επιτραπέζιους υπολογιστές, το Flutter χρησιμοποιεί το περίβλημα παραθύρου Flutter Desktop, για web — τη μηχανή CanvasKit (WebGL) ή τον renderer HTML.
Το Flutter επιτυγχάνει 60/120 FPS χάρη στη δική του 2D μηχανή (Skia/Impeller), στην απουσία native bridge (σε αντίθεση με το React Native), στα τρία δέντρα (Widget → Element → Render) με επαναχρησιμοποίηση Element σε αμετάβλητο τύπο/key, στον αλγόριθμο διάταξης με μονόδρομο πέρασμα (constraints down, sizes up) και στο RepaintBoundary για απομόνωση της εκ νέου σχεδίασης μεμονωμένων ζωνών οθόνης.
Συμπέρασμα
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης