Flutter: Das Center-Widget im Detail
Zuletzt aktualisiert:
6 Min. Lesezeit

Center setzt ein einzelnes Kind in die Mitte des Bereichs, den es zugewiesen bekommt. Technisch ist es ein Align mit fest verdrahtetem alignment: Alignment.center – mit exakt denselben Größenregeln. Ein Ladeindikator, die Meldung für eine leere Liste, ein Login-Formular, der Inhalt eines Dialogs: Überall, wo Sie „zentrieren“ denken, greifen Sie zuerst zu Center. Das Widget wirkt trivial, trotzdem tauchen immer dieselben drei Fragen auf: Warum zentriert es in einer Column nicht vertikal, warum füllt es den ganzen Bildschirm, und wie zentriere ich auf einer scrollbaren Seite? Genau darum geht es hier.
Live-Demo: Beispiele zum Center-Widget
Probieren Sie das Center-Widget im interaktiven Beispiel unten in verschiedenen Szenarien aus:
💡 Falls das Beispiel oben nicht lädt, klicken Sie auf DartPad, um es in einem neuen Tab auszuführen.
Grundlegende Verwendung
Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
)Center richtet horizontal und vertikal aus und nimmt genau ein child auf. Da der Scaffold-Body eine begrenzte Box liefert, wächst Center auf den gesamten Body und der Indikator landet exakt in der Bildschirmmitte. Das ist der häufigste Fall, und er überrascht praktisch nie. Überraschungen beginnen erst, wenn Center in einer Column, einer Row oder einem scrollbaren Widget steckt.
Warum füllt Center den gesamten Bereich?
Center bemisst sich nach derselben Regel wie Align: Gibt der Parent auf einer Achse eine begrenzte Constraint vor, nimmt Center auf dieser Achse die größtmögliche Ausdehnung; ist die Constraint unbegrenzt, schrumpft es auf sein Kind. Zentrieren ergibt nur dann einen Sinn, wenn rundherum Platz übrig ist – deshalb ist „so groß wie möglich“ die vernünftige Voreinstellung. Wenn Sie im Flutter Inspector ein Center auswählen und die markierte Fläche den ganzen Parent bedeckt, ist das kein Fehler.
Dieses Verhalten lässt sich mit widthFactor und heightFactor ändern:
Center(
widthFactor: 1, // Breite von Center = Breite des Kindes
heightFactor: 2, // Höhe von Center = doppelte Höhe des Kindes
child: Text('Eng umschlossen'),
)Mit widthFactor: 1 und heightFactor: 1 legt sich Center eng um sein Kind. Die zentrierende Wirkung verschwindet, dafür aber auch das Wachstum – praktisch, wenn Center sonst einen Stack oder einen sich am Kind orientierenden Parent aufblähen würde. Ein Wert wie 2 lässt rund um das Kind Platz proportional zu dessen eigener Größe.
Center innerhalb einer Column
Eine Column gibt ihren Kindern eine begrenzte Breite, aber eine unbegrenzte Höhe. Deshalb ist ein Center in einer Column über die volle Breite gespannt, aber nur so hoch wie sein Kind: Es zentriert ausschließlich horizontal. Für die vertikale Zentrierung ist die Column selbst zuständig:
// Zentriert horizontal, nicht vertikal
Column(
children: [
Center(child: Text('Nur horizontal zentriert')),
],
)
// Zentriert alle Kinder vertikal
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Vertikal zentriert'),
],
)
// Zentriert die ganze Column auf beiden Achsen
Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.inbox, size: 64),
SizedBox(height: 16),
Text('Noch keine Inhalte'),
],
),
)Entscheidend im dritten Beispiel ist mainAxisSize: MainAxisSize.min: Eine Column dehnt sich standardmäßig über jeden angebotenen Pixel Höhe aus, und dann bleibt Center kein Platz zum Zentrieren. Dieses Verhalten habe ich im Beitrag zu mainAxisSize ausführlich beschrieben. Für ein einzelnes Kind können Sie das Center auch weglassen und stattdessen crossAxisAlignment: CrossAxisAlignment.center an der Column setzen – der Unterschied: crossAxisAlignment betrifft alle Kinder, nicht nur eines.
Center innerhalb einer Row
Eine Row gibt unbegrenzte Breite, also schrumpft Center auf sein Kind und es bleibt nichts übrig, worin zentriert werden könnte. Wenn Sie in einer Row „diesen Text zentrieren“ möchten, packen Sie das Center in ein Expanded; Expanded liefert eine begrenzte Box und die Zentrierung greift:
Row(
children: [
Icon(Icons.arrow_back),
Expanded(
child: Center(child: Text('Titel')),
),
Icon(Icons.more_vert),
],
)Die gesamte Breite zwischen den beiden Icons geht an das Center, der Titel sitzt mittig darin. Warum Expanded genau das leistet, erklärt der Beitrag zu Expanded.
Wann verwenden – und wann nicht?
Greifen Sie zu Center, wenn:
- ein einzelnes Widget in die Mitte einer begrenzten Box soll (Scaffold-Body, Container, Card, Expanded);
- Sie einen Dialog, einen leeren Zustand oder einen Ladebildschirm bauen – Layouts mit genau einem Element in der Mitte;
- Sie ein Kind innerhalb eines Stack oder einer SizedBox zentrieren.
Greifen Sie zu etwas anderem, wenn:
- Sie eine andere Position als die Mitte brauchen – dann
Align; - Sie alle Kinder einer Row oder Column ausrichten – dann
mainAxisAlignmentundcrossAxisAlignment; - ohnehin schon ein Container vorhanden ist –
Container(alignment: Alignment.center)erledigt dasselbe, ohne ein zusätzliches Widget im Baum; - die Zeilen eines mehrzeiligen Textes mittig stehen sollen – dann
textAlign: TextAlign.center. Center zentriert die Textbox, nicht die Zeilen darin.
Häufige Fehler
1. Center zentriert in einer SingleChildScrollView nicht vertikal
Symptom: Ein kurzes Formular klebt oben an einer scrollbaren Seite. SingleChildScrollView gibt unbegrenzte Höhe, Center schrumpft auf sein Kind und hat nichts, wogegen es zentrieren könnte. Lösung: Entweder das Center aus dem scrollbaren Bereich herausziehen (siehe Szenario unten) oder dem Inhalt mindestens die Bildschirmhöhe geben:
LayoutBuilder(
builder: (context, constraints) => SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: Center(child: Text('Kurzer Inhalt mittig, langer Inhalt scrollt')),
),
),
)2. Die Column im Center nimmt die volle Höhe ein
Symptom: Sie haben Center(child: Column(...)) geschrieben, der Inhalt beginnt trotzdem oben. Der Standardwert von mainAxisSize ist max, die Column verbraucht also die gesamte Höhe, die Center ihr anbietet. Ergänzen Sie mainAxisSize: MainAxisSize.min oder lassen Sie die Column ihre Kinder mit mainAxisAlignment: MainAxisAlignment.center selbst zentrieren.
3. Langer Text wirkt nicht zentriert
Symptom: Der Textblock sitzt mittig, die Zeilen sind aber linksbündig. Center zentriert die Box des Text-Widgets; sobald der Text umbricht, richten sich die Zeilen innerhalb dieser Box standardmäßig links aus. Setzen Sie Text('...', textAlign: TextAlign.center).
4. Center bläht den umgebenden Stack auf
Symptom: Sie wollten eine kleine zentrierte Ebene über einem Icon legen, und der Stack breitet sich über den ganzen Bildschirm aus. Center wächst in einer begrenzten Box, und ein Stack richtet sich nach seinem größten nicht positionierten Kind – also wächst der Stack mit. Geben Sie dem Stack über eine SizedBox eine Größe oder ergänzen Sie am Center widthFactor: 1, heightFactor: 1. Dasselbe Problem und die Alternative mit Positioned finden Sie im Beitrag zu Align, die Größenregeln des Stacks im Beitrag zu Stack und Positioned.
Mini-Szenario: zentrierter und scrollbarer Login-Bildschirm
Stellen Sie sich einen Login-Bildschirm vor: Auf großen Displays soll das Formular mittig stehen und nie breiter als 400 Pixel werden, auf kleinen soll der Inhalt scrollen, sobald die Tastatur erscheint.
class LoginScreen extends StatelessWidget {
const LoginScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const FlutterLogo(size: 72),
const SizedBox(height: 32),
const TextField(decoration: InputDecoration(labelText: 'E-Mail')),
const SizedBox(height: 16),
const TextField(
obscureText: true,
decoration: InputDecoration(labelText: 'Passwort'),
),
const SizedBox(height: 24),
FilledButton(onPressed: () {}, child: const Text('Anmelden')),
],
),
),
),
),
),
);
}
}Die Reihenfolge ist bewusst gewählt: Center außen, SingleChildScrollView innen. Center bekommt vom Scaffold die begrenzte Box und wächst hinein; die Scroll-View bemisst sich an ihrem Inhalt, und Center zentriert diesen. Ist der Inhalt höher als der Bildschirm, nimmt die Scroll-View die volle Höhe ein und scrollt einfach – nichts wirkt verschoben, weil dann kein Restplatz mehr zu verteilen ist. Erscheint die Tastatur, verkleinert das Scaffold den Body und derselbe Mechanismus greift erneut. ConstrainedBox(maxWidth: 400) verhindert, dass sich das Formular auf einem Tablet über die ganze Breite zieht, und mainAxisSize: MainAxisSize.min hält die Column so hoch wie ihr Inhalt. Das Padding habe ich absichtlich als SingleChildScrollView.padding gesetzt, damit die Ränder mitscrollen; Details dazu im Beitrag zu Padding.
Häufig gestellte Fragen
Worin unterscheiden sich Center und Align?
In nichts: Center ist ein Align mit fest gesetztem alignment: Alignment.center und bietet dieselben Parameter widthFactor und heightFactor sowie dieselben Größenregeln. Wenn Sie nur zentrieren, liest sich Center besser; brauchen Sie eine andere Position, nehmen Sie Align.
Warum ist Center größer als sein Kind?
Weil Center bei einer begrenzten Constraint den gesamten angebotenen Platz einnimmt – Zentrieren ergibt nur Sinn, wenn rundherum Platz vorhanden ist. Soll es sich eng um das Kind legen, setzen Sie widthFactor: 1 und heightFactor: 1.
Warum zentriert Center in einer Column nicht vertikal?
Eine Column gibt unbegrenzte Höhe, Center findet also keine Höhe zum Zentrieren und schrumpft auf sein Kind. Setzen Sie an der Column mainAxisAlignment: MainAxisAlignment.center oder packen Sie die Column mit mainAxisSize: MainAxisSize.min in ein Center.
Center oder mainAxisAlignment?
Center, um ein einzelnes Kind auf beiden Achsen in die Mitte zu setzen. mainAxisAlignment, um mehrere Kinder einer Row oder Column entlang der Hauptachse zu verteilen (center, spaceBetween, spaceEvenly). Beides lässt sich kombinieren: Center positioniert die äußere Box, mainAxisAlignment ordnet den Inhalt darin.
Verwandte Artikel
Flutter: Feine Ausrichtung mit dem Align-Widget
Präzise Platzierung mit Align: Koordinatensystem Alignment(x, y), FractionalOffset, widthFactor und heightFactor, Align oder Positioned im Stack, Fehler.
Flutter: ListView-Widget verwenden
Flutter-ListView-Leitfaden: Lazy Loading mit builder, separated, itemExtent, was shrinkWrap wirklich kostet und die Lösung für den Unbounded-Height-Fehler.
Flutter: GridView-Widget verwenden
Flutter-GridView-Leitfaden: count, extent und builder, die beiden Grid-Delegates, der childAspectRatio-Overflow-Fehler und die wahren Kosten von shrinkWrap.