Einführung in Flutter: Widget-Baum, Row, Column und Stack
Endlich habe ich mit Flutter angefangen!
Heute ist ein historischer Tag! Nachdem ich die Dart-Grundlagen gelernt habe, bin ich endlich zu Flutter gewechselt. Mein erster Eindruck: Widgets, Widgets, überall Widgets!
Live-Demo: Beispiele zu Row, Column und Stack
Probieren Sie die grundlegenden Layout-Strukturen von Flutter interaktiv aus:
💡 Falls das Beispiel oben nicht lädt, klicken Sie auf DartPad, um es in einem neuen Tab auszuführen.
Den Aufbau von Flutter verstehen
Das Erste, was mir in einem Flutter-Projekt auffiel, war dies: Alles ist wie eine Baumstruktur. Es beginnt mit der main-Funktion, dann das App-Widget, dann die Seite, dann das Scaffold … eine verschachtelte Struktur.
Grundaufbau einer Flutter-App
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp()); // App starts here
}Die Funktion main() ist der Ausgangspunkt von allem. Mit runApp() starten wir unsere App.
Das Haupt-Widget (MyApp)
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'First App',
debugShowCheckedModeBanner: false, // Remove debug banner
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'My First Project'),
);
}
}MaterialApp erlaubt es, Apps in Flutter nach den Regeln des Material Design zu bauen. Der Parameter home legt die erste Seite fest, die geöffnet wird.
Das Seiten-Widget (MyHomePage)
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}StatefulWidget ist für Widgets gedacht, deren Zustand sich ändern kann. Wenn Sie zum Beispiel einen Zähler mit Button bauen, muss sich die Anzeige bei jeder Änderung aktualisieren. Genau dafür ist StatefulWidget da.
Die State-Klasse
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
print("Page loaded!");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Text("Hello Flutter!"),
),
);
}
}initState() läuft einmal beim ersten Öffnen der Seite. Hier werden üblicherweise API-Aufrufe untergebracht.
Scaffold ist das Grundgerüst einer Seite. Es enthält Bereiche wie AppBar (obere Leiste), body (Inhalt) und bottomNavigationBar.
Die Baumstruktur von Flutter
Der Schlüssel zum Verständnis von Flutter ist diese Baumstruktur:
Main
└─ MyApp (MaterialApp)
└─ MyHomePage (Scaffold)
├─ AppBar
└─ Body
└─ Widgets...Alles ist ineinander verschachtelt. Stellen Sie es sich so vor: Es gibt ein Gebäude (MaterialApp), das Gebäude hat Räume (Scaffold), und in den Räumen stehen Möbel (Widgets).
Layout gestalten: Row, Column und Stack
Für das Layout gibt es in Flutter drei grundlegende Strukturen. Anfangs war ich unsicher, wann ich welche einsetzen soll.
Row – horizontale Anordnung
Row ordnet Widgets nebeneinander an, von links nach rechts.
Row(
children: [
Container(width: 80, height: 80, color: Colors.blue),
Container(width: 80, height: 80, color: Colors.red),
Container(width: 80, height: 80, color: Colors.yellow),
],
)Ausgabe auf dem Bildschirm: 🟦🟥🟨 (drei Quadrate nebeneinander)
Column – vertikale Anordnung
Column ordnet Widgets untereinander an, von oben nach unten.
Column(
children: [
Container(width: 80, height: 80, color: Colors.blue),
Container(width: 80, height: 80, color: Colors.red),
Container(width: 80, height: 80, color: Colors.yellow),
],
)Ausgabe auf dem Bildschirm:
🟦
🟥
🟨(drei Quadrate untereinander)
Stack – überlappende Anordnung
Stack legt Widgets übereinander, wie Ebenen.
Stack(
children: [
Container(width: 130, height: 100, color: Colors.blue),
Container(width: 80, height: 70, color: Colors.red),
Container(width: 30, height: 60, color: Colors.yellow),
],
)Unten die große blaue Box, in der Mitte die mittlere rote, oben die kleine gelbe. Alle sind an der oberen linken Ecke ausgerichtet.
Row und Column kombinieren
Nun bauen wir ein etwas komplexeres Layout und kombinieren Zeilen und Spalten:
Ziel: 2 Zeilen mit je 4 Spalten (insgesamt 8 Kästchen)
Column(
children: [
// First row
Row(
children: [
Container(width: 80, height: 80, color: Colors.yellow),
Container(width: 80, height: 80, color: Colors.red),
Container(width: 80, height: 80, color: Colors.green),
Container(width: 80, height: 80, color: Colors.blue),
],
),
// Second row
Row(
children: [
Container(width: 80, height: 80, color: Colors.red),
Container(width: 80, height: 80, color: Colors.blue),
Container(width: 80, height: 80, color: Colors.yellow),
Container(width: 80, height: 80, color: Colors.green),
],
),
],
)Ergebnis:
🟨 🟥 🟩 🟦
🟥 🟦 🟨 🟩Die Logik ist folgende: Die Hauptstruktur ist eine Column (vertikal). Darin liegen zwei Rows (horizontal). Jede Row enthält vier Container.
Das Container-Widget
Container ist eines der grundlegendsten Widgets in Flutter. Stellen Sie es sich als Kasten vor.
Einfacher Container
Container(
width: 100,
height: 100,
color: Colors.blue,
child: Text("Hello"),
)Inhalt zentrieren
Container(
width: 100,
height: 100,
color: Colors.blue,
child: Center(
child: Text(
"Hello",
style: TextStyle(color: Colors.white),
),
),
)Das Widget Center zentriert das, was in ihm liegt.
Margin und Padding
Container(
width: 100,
height: 100,
margin: EdgeInsets.all(10), // Outer spacing
padding: EdgeInsets.all(20), // Inner spacing
color: Colors.blue,
child: Text("Hello"),
)- Margin: Abstand außerhalb des Containers
- Padding: Abstand innerhalb des Containers
Ecken abrunden
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(20),
),
child: Center(
child: Text("Rounded"),
),
)Wenn Sie decoration verwenden, müssen Sie den Parameter color innerhalb von decoration angeben.
Rahmen hinzufügen
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.blue,
width: 3,
),
),
child: Center(
child: Text("Bordered"),
),
)Ausrichtung in Row und Column
Wir können Widgets dort ausrichten, wo wir sie haben möchten:
MainAxisAlignment
Row(
mainAxisAlignment: MainAxisAlignment.center, // Center
children: [
Container(width: 50, height: 50, color: Colors.red),
Container(width: 50, height: 50, color: Colors.blue),
],
)Bei einer Row verläuft die Hauptachse horizontal. Die Optionen:
start: Links ausrichtenend: Rechts ausrichtencenter: ZentrierenspaceBetween: Gleicher Abstand dazwischenspaceAround: Gleicher Abstand ringsumspaceEvenly: Überall gleicher Abstand
CrossAxisAlignment
Row(
crossAxisAlignment: CrossAxisAlignment.center, // Center vertically
children: [
Container(width: 50, height: 50, color: Colors.red),
Container(width: 50, height: 100, color: Colors.blue),
],
)Bei einer Row verläuft die Querachse vertikal. Die Optionen:
start: Oben ausrichtenend: Unten ausrichtencenter: Zentrierenstretch: Dehnen
Praxisbeispiel: Layout eines Taschenrechners
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// Screen
Container(
width: double.infinity,
height: 100,
color: Colors.grey[300],
child: Center(
child: Text(
"0",
style: TextStyle(fontSize: 48),
),
),
),
// Buttons
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
createButton("7"),
createButton("8"),
createButton("9"),
createButton("/"),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
createButton("4"),
createButton("5"),
createButton("6"),
createButton("*"),
],
),
],
)Was ich am ersten Tag mitgenommen habe
- In Flutter ist alles ein Widget
- Row horizontal, Column vertikal, Stack überlappend
- Container ist das Widget, das ich am häufigsten nutzen werde
- Ausgerichtet wird mit MainAxisAlignment und CrossAxisAlignment
- Scaffold ist das Grundgerüst einer Seite
Morgen schaue ich mir Buttons, State Management und dynamische Inhalte an. Diese Flutter-Reise ist wirklich spannend!
Nützliche Ressourcen
Möchten Sie Flutter mit mir lernen?
Bleiben Sie dran und lernen Sie Flutter weiter! 🚀