3.2 Vertiefung zu Layout-Widgets
Zur Ausrichtung eines einzelnen Widget (z.B. eines Text– oder Image-Widgets) eignet sich das Container-Widget ganz gut. Aber sobald wir mehrere Widgets besitzen, die wir zueinander ausrichten möchten, sind wir auf Mehrkind-Widgets wie das Column– oder Row-Widget angewiesen.
Übung
Column-Widget um Container-Widgets erweitern
In Kapitel 2.4 haben Sie Column-Widgets bereits kennengelernt und Sie wissen, dass nach dem Parameter children: in den eckigen Klammern eine Auflistung von Widgets folgt. Ergänzen Sie den bereitgestellten Code um drei Container-Widgets in den Farben Grün, Weiss und Rot mit einer Höhe und Breite von je 100 Pixel.
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
body: SafeArea(
child: Column(
children: [
// hier Code für die drei Container-Widgets einfügen
],
),
),
),
);
}
}
Ausrichtung von Widgets entlang der vertikalen Achse
In Visual Studio Code sehen Sie über den Flutter Widget Inspector, dass die Column-Widgets in die vertikale Richtung den ganzen Ihnen zur Verfügung stehenden Raum einnehmen. In die horizontale Richtung sind die Column-Widgets durch die Breite der Container-Kinder limitiert.
Die Ausbreitung in die vertikale Richtung kann durch den Code mainAxisSize: mainAxisSize.min beschränkt werden.
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
body: SafeArea(
child: Column(
// 1
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: 100,
width: 100,
color: Colors.green,
child: Text('Container 1')),
Container(
height: 100,
width: 100,
color: Colors.white,
child: Text('Container 2')),
Container(
height: 100,
width: 100,
color: Colors.red,
child: Text('Container 3'))
],
),
),
),
);
}
}
- Durch den Parameter mainAxisSize.min wird der rote Rahmen in die vertikale Richtung geschrumpft.
Aktuell werden die Container-Widgets der Reihe nach von oben nach unten aufgelistet. Ersetzen Sie den Code // 1 mainAxisSize: mainAxisSize.min durch den Code verticalDirection: VerticalDirection.up um eine Auflistung der Widgets von unten nach oben zu erreichen.
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
body: SafeArea(
child: Column(
verticalDirection: VerticalDirection.up,
children: [
Container(
height: 100,
width: 100,
color: Colors.green,
child: Text('Container 1')),
Container(
height: 100,
width: 100,
color: Colors.white,
child: Text('Container 2')),
Container(
height: 100,
width: 100,
color: Colors.red,
child: Text('Container 3'))
],
),
),
),
);
}
}
Um die Position als auch die Abstände der Container-Widgets untereinander anzupassen, können Sie auf den mainAxisAlignment-Parameter zugreifen. Wenn Sie aus dem letzten Beispiel die Zeile mit dem Code verticalDirection: VerticalDirection.up durch den Code mainAxisAlignment: MainAxisAlignment.spaceEvenly ersetzen, können Sie die Abstände unter den Widgets vergrössern.
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
Über mainAxisAlignment: MainAxisAlignment.spaceBetween erreichen Sie, dass ein Widget an die obere Bildschirmhälfte und das andere Widget an die untere Bildschirmhälfte geheftet wird und alle Widgets, die sich dazwischen befinden, zwischen dem obersten und untersten Widget zu liegen kommen.
mainAxisAlignment: MainAxisAlignment.spaceBetween,
Ausrichtung von Widgets entlang der horizontalen Achse
Die Ausrichtung der Container-Widgets lässt sich natürlich auch entlang der horizontalen Achse verändern. Dafür setzt man bei einem Column-Widget den crossAxisAlignment-Parameter ein. Dort entspricht die Kreuzachse der horizontalen Achse. Bei einem Row-Widget entspricht die Hauptachse der horizontalen Achse und die Kreuzachse der vertikalen Achse.
Wenn wir zu unserem letzten Beispiel zurück gehen und die Zeile mit dem Code mainAxisAlignment: MainAxisAlignment.spaceBetween, durch crossAxisAlignment: CrossAxisAlignment.start, oder crossAxisAlignment: CrossAxisAlignment.end, ersetzen, ändert sich nach einem Hot-Reload noch nichts.
...
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(...),
Container(...),
Container(...),
],
...
...
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(...),
Container(...),
Container(...),
],
...
crossAxisAlignment versucht, die Kinder-Widgets entlang der Kreuzachse auszurichten. In unserem Beispiel besitzen alle Kinder-Widgets eine Breite von 100 Pixel, also ändert sich bei der Ausrichtung erst etwas, sobald eines der Container-Widgets eine Breite besitzt, die kleiner oder grösser als 100 Pixel ist. Kopieren Sie den untenstehenden Code zur Veranschaulichung.
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 100,
width: 300,
color: Colors.green,
child: Text('Container 1')),
Container(
height: 100,
width: 100,
color: Colors.white,
child: Text('Container 2')),
Container(
height: 100,
width: 100,
color: Colors.red,
child: Text('Container 3'))
],
),
),
),
);
}
}
Sie sehen, dass wenn das erste Container-Widget eine Breite von z.B. 300 Pixel besitzt, der Code crossAxisAlignment: CrossAxisAlignment.start, oder crossAxisAlignment: CrossAxisAlignment.end, dazu führt, dass die anderen beiden Container-Widgets an dem linken (CrossAxisAlignment.start) oder rechten Rand (CrossAxisAlignment.end) des breitesten Widgets ausgerichtet werden.
Falls Sie alle Container-Widgets entlang der rechten Bildschirmhälfte ausrichten möchten, müssen Sie zum Code einen vierten, unsichtbaren Container mit einer unendlichen Breite hinzufügen.
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
height: 100,
width: 100,
color: Colors.green,
child: Text('Container 1')),
Container(
height: 100,
width: 100,
color: Colors.white,
child: Text('Container 2')),
Container(
height: 100,
width: 100,
color: Colors.red,
child: Text('Container 3')),
Container(
width: double.infinity,
)
],
),
),
),
);
}
}
Der unsichtbare Container entspricht der Linie, auf die der rote Pfeil zeigt. Dieser Container besitzt keine Höhe und eine unendliche Breite (also die maximale Breite, welche der Bildschirm des Geräts zulässt). Dieser unsichtbare Container drückt all unsere Kinder auf die rechte Bildschirmhälfte, da wir mit dem Code crossAxisAlignment: CrossAxisAlignment.end alle Kinder-Widgets entlang dem Ende der horizontalen Achse ausrichten.
Über crossAxisAlignment: CrossAxisAlignment.stretch können Sie dieContainer auf die gesamte Breite des Bildschirms ausweiten.
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 100,
width: 100,
color: Colors.green,
child: Text('Container 1')),
Container(
height: 100,
width: 100,
color: Colors.white,
child: Text('Container 2')),
Container(
height: 100,
width: 100,
color: Colors.red,
child: Text('Container 3')),
],
),
),
),
);
}
}
Was ist nun, wenn Sie ein wenig Abstand zwischen Ihren Container-Widgets haben möchten? Kein Problem, da schafft das SizedBox-Widget Abhilfe. Das untere Beispiel zeigt, wie wir mit Hilfe von SizedBox-Widgets zwischen allen Container-Widgets ein Abstand von 30 Pixel einfügen können. Für ein vertikal ausgerichtetes Column-Widget reicht beim SizedBox-Widget die Angabe einer Höhe (height).
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 100,
width: 100,
color: Colors.green,
child: Text('Container 1')),
SizedBox(
height: 30,
),
Container(
height: 100,
width: 100,
color: Colors.white,
child: Text('Container 2')),
SizedBox(
height: 30,
),
Container(
height: 100,
width: 100,
color: Colors.red,
child: Text('Container 3')),
],
),
),
),
);
}
}
Row-Widgets
Alles was wir bisher über Column-Widgets gelernt haben, gilt natürlich auch für Row-Widgets. Für ein Row-Widget verläuft die Hauptachse in die horizontale Richtung. Wenn wir in unserem bisherigen Code Column durchRow ersetzen, werden die Container-Widgets entlang der vertikalen Achse ausgerichtet, da die Kreuzachse CrossAxisAlignment.stretch eines Row-Widgets in die vertikale Richtung verläuft. Für das SizedBox-Widget aus dem letzten Beispiel ergibt der height Parameter dann natürlich wenig Sinn und muss durch einen width Parameter ersetzt werden.
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
body: SafeArea(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 100,
width: 100,
color: Colors.green,
child: Text('Container 1')),
SizedBox(
width: 30,
),
Container(
height: 100,
width: 100,
color: Colors.white,
child: Text('Container 2')),
SizedBox(
width: 30,
),
Container(
height: 100,
width: 100,
color: Colors.red,
child: Text('Container 3')),
],
),
),
),
);
}
}
Übung
Nachdem Sie sich nun mit Column– und Row-Widgets und deren Verwendung zum Layout Ihrer App vertraut gemacht haben, ist es an der Zeit, Ihr Verständnis zu testen. Verwenden Sie Ihr vorhandenes Flutter-Projekt, um dieses Layout zu erstellen.
Wenn Sie das gewünschte Aussehen erreicht haben und mit Ihrer Lösung zufrieden sind, können Sie den Code wieder aus Ihrem aktuellen Flutter-Projekt löschen.
Lösung
es war nicht klar, dass mainAxisSize.min zu ersetzen war.
Liebe Mar, vielen Dank für Ihren Hinweis. Die Anleitung wurde entsprechend angepasst.