İçeriğe geç / Skip to content / Zum Inhalt
Ahmet Balaman LogoAhmet Balaman

Einführung in Flutter: Widget-Baum, Row, Column und Stack

Ahmet Balaman
FlutterWidgetRowColumnStackUI Design

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 ausrichten
  • end: Rechts ausrichten
  • center: Zentrieren
  • spaceBetween: Gleicher Abstand dazwischen
  • spaceAround: Gleicher Abstand ringsum
  • spaceEvenly: Ü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 ausrichten
  • end: Unten ausrichten
  • center: Zentrieren
  • stretch: 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! 🚀

Kommentare