Was ist ein Stack Element?
In einem Stack Element kannst du so viele Elemente, wie du willst stapeln oder überlappen. Dies hilft dir dabei komplexere Widgets in deiner App darzustellen, wenn du deren Aussehen oder Funktionalität übernehmen willst, ohne andere Widgets nachbauen zu müssen. So kann das zum Beispiel aussehen:


Wie funktioniert es?
Ein Stack
Element hat ein children: <Widget> []
Attribut, dem du so viele Widgets wie du willst geben kannst. Diese überlagern sich gegenseitig, je nachdem an welcher Stelle die Widgets stehen.
Stack(
children: <Widget>[
UnteresWidget(),
MittleresWidget(),
OberesWidget(),
],
),
Die Reihenfolge der verwendeten Flutter Widgets, die gestackt werden sollen, ist wichtig, denn das erste angegebene Widget liegt visuell auf der untersten Ebene, wie in der folgenden Grafik zu sehen ist:

Ein Stack
Element ist immer so groß wie das größte Widget im Stack und nach oben links ausgerichtet, wenn keine weiteren Angaben gemacht werden.
Ein gutes Beispiel dafür:
Stack(
children: <Widget>[
Container(
color: Color(0xff619ff9),
),
Container(
color: Colors.white24,
height: 300.0,
width: 300.0,
),
Container(
color: Colors.white24,
height: 150.0,
width: 150.0,
)
],
),

Wie man hier sehen kann, berücksichtigt das Stack
Element sogar Transparenz, da Colors.white24
ein von Flutter vorgegebenes Weiß mit 12% Transparenz ist.
Ausrichtung
Wie schon erwähnt und im oberen Beispiel zu sehen ist, werden alle Elemente standardmäßig oben links ausgerichtet. Diese Richtung kannst du über das alignment
Attribut konfigurieren:
Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[],
),
Wenn du aber nur gewisse Elemente anders ausrichten oder verschiedene Ausrichtungen nutzen möchtest, kannst du hier das Align
Widget nutzen, welches nur innerhalb von Stack
s verwendet werden kann:
Stack(
children: <Widget>[
Container(
color: Color(0xff619ff9),
),
Container(
color: Colors.white24,
height: 300.0,
width: 300.0,
),
Align(
alignment: Alignment.centerLeft,
child: Container(
color: Colors.white24,
height: 150.0,
width: 150.0,
),
),
],
),

Hier kannst du auch wieder sehen, wie gut sich Transparenz mit Stack
Elementen kombinieren lässt.
Positionierung
Ähnlich wie das Align
Element gibt es ein Positioned
Element, mit dem du die Elemente innerhalb eines Stacks genau so positionieren kannst, wie du willst. Es hat die Attribute top
, left
, right
und bottom
. Diese geben an wie weit das Element von besagter Seite entfernt ist.
So kannst du also, durch das Angeben von zwei der Attribute, ein Element sehr genau platzieren:
Positioned(
top: 50.0,
left: 200.0,
height: 150.0,
width: 150.0,
child: Container(
color: Colors.white24,
),
),

Wie du im Beispiel sehen kannst, kommt das Positioned
Element mit width
und height
Attributen. Diese kannst du setzen, um die Größe des child
Elements zu bestimmen, sollte dieses nicht von sich aus Größen bestimmende Attribute haben.
Indexed Stack?
Das Stack
Element hat auch noch einen Bruder und zwar den IndexedStack
. Ein Indexedstack
ist wie ein normaler Stack
, allerdings zeigt er immer nur ein Element an, das anhand eines Indexes gesteuert wird. Dieser Index ist ganz einfach das index
Attribut, mit dem die angezeigte Schicht zur Laufzeit auch geändert werden kann. Dies kann insbesondere bei Animationen in Flutter sehr hilfreich sein.
Um das Ganze zu verdeutlichen hier ein kleines Beispiel eines normalen Stacks:
Stack(
alignment: Alignment.center,
children: <Widget>[
Container(
color: Color(0xff619ff9),
),
Container(
height: 300.0,
width: 300.0,
color: Color(0xFF61c9f9),
),
Container(
height: 150.0,
width: 150.0,
color: Color(0xFF61def9),
),
],
),

Nun können wir das Ganze zu einem IndexedStack
machen und dem FloatingActionButton
eine Funktion geben, die dem index
Attribut des IndexedStack
eine neue zufällige Nummer zuweist:
import 'dart:math';
import 'package:flutter/material.dart';
class IndexedStackPage extends StatefulWidget {
IndexedStackPage({Key? key}) : super(key: key);
_IndexedStackPageState createState() => _IndexedStackPageState();
}
class _IndexedStackPageState extends State<IndexedStackPage> {
int stackIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Indexed Stack Beispiel'),
),
body: IndexedStack(
index: stackIndex,
alignment: Alignment.center,
children: <Widget>[
Container(
color: Color(0xff619ff9),
),
Container(
height: 300.0,
width: 300.0,
color: Color(0xFF61c9f9),
),
Container(
height: 150.0,
width: 150.0,
color: Color(0xFF61def9),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() {
stackIndex = generateNewRandomIndex(stackIndex);
}),
tooltip: 'Shuffle elements',
child: Icon(Icons.shuffle),
),
);
}
int generateNewRandomIndex(int index) {
int oldInt = index;
int newInt;
do {
newInt = new Random().nextInt(3);
} while (newInt == oldInt);
return newInt;
}
}
Und Ta-Da! Wie man sieht, kann man den FloatingActionButton
drücken und es wird immer eine andere der drei Schichten angezeigt:

Fazit
Und so einfach ist es, mit diesen zwei Flutter Widgets komplexe Widgets zu erstellen, ohne alles selbst designen zu müssen.
Der ganze Code und die Beispiele sind in unserem GitHub hier zu finden. Einfach auschecken, ausprobieren und ganz einfach nachbauen.