3.1 Einführung (inkl. Theorie zu Layout Widgets)
Dieses Projekt sollten Sie alleine in Angriff nehmen.
Was ist das Ziel?
Im letzten Kapitel haben Sie gelernt, wie man die Demo-App zu einer Rezepte-App umbaut und haben ein paar elementare Konzepte aus der OOP kennengelernt. Ziel dieses Kapitels ist die Erstellung einer Visitenkarten-App, die alle wichtigen Angaben zu Ihrer Person enthält. Dabei sollten Sie lernen, wie sich die Benutzeroberfläche einer Flutter-App unter Benutzung von Layout-Widgets gestalten lässt.
Wir empfehlen allen Schüler:innen die Kapitel 3.1 – 3.3 zu bearbeiten. Für das Styling (Einsatz von alternativen Schriften, Icons oder anderen Designelementen) lassen wir Ihnen freie Hand, da Programmierung auch eine kreative Arbeit sein sollte. Falls Sie aber auch für den Styling-Teil froh um eine Anleitung sind, dürfen Sie gerne die restlichen Teile aus Kapitel 3 bearbeiten.
Neue Flutter-App erstellen und Hintergrundfarbe ändern
- Erstellen Sie in VS Code ein neues Flutter Projekt (hier können Sie nachlesen, wie das geht).
- Warten Sie bis das Flutter Projekt erstellt wurde und im Ordner lib die main.dart Datei erscheint.
- Ersetzen Sie den Inhalt von main.dart mit dem folgenden Code und starten Sie die App auf ihrem virtuellen oder physischen Gerät:
import 'package:flutter/material.dart'; main() => runApp(MyApp()); class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( home: Scaffold( backgroundColor: Colors.lightBlue, ), ); } }
Theorie
Layout-Widgets
Sobald Sie ein neues Flutter-Widget verwenden, lohnt es sich immer zuerst einen Blick in die Dokumentation zu werfen. Im Widget Katalog findet man z.B. alle Informationen zu Layout-Widgets, welche für die Anordnung von Widgets verwendet werden.
Man unterscheidet grob zwischen Einzelkind-Widgets (single-child-Widgets) und Mehrkind-Widgets (multi-child-Widgets).
- Einzelkind-Widgets werden verwendet, wenn man nur ein einzelnes Widget darstellen will (z.B. ein Text oder Image-Widget).
- Mehrkind-Widgets werden verwendet, wenn man mehrere Widgets darstellen will (z.B. mehrere Text-Widgets oder ein Text– und fünf Image-Widgets). Das Column-Widget aus Kapitel 2.4 ist ein Vertreter aus der Klasse der Mehrkind-Widgets.
Experimente mit Container-Widgets
Zur Gestaltung von Flutter-Apps sind Container-Widgets nützlich. Container-Widgets werden zum Vergrössern, Verkleinern und die Positionierung von anderen Widgets verwendet. Container-Widgets sind Einzelkind-Widgets, das bedeutet, dass Sie z.B. ein einzelnes Text oder Image-Widget aufnehmen können. In der Dokumentation zur Container-Klasse kann man nachlesen, dass Container ohne child-Widgets immer probieren so gross wie möglich zu sein. Zur Illustration dient der folgende Code:
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
body: Container(
color: Colors.white,
),
),
);
}
}
Im Code wird das Scaffold-Widget um ein Container-Widget erweitert, welche als color-Attribut die Farbe Weiss zugewiesen bekommt. Nach einem Hot-Reload können Sie sehen, dass das Container-Widget den ganzen ihm zur Verfügung stehenden Raum einnimmt und die Hintergrundfarbe überdeckt.
Wenn Sie das Container-Widget aber um ein child-Widget erweitern, reduziert sich die Grösse des Container-Widget auf die Grösse des child-Widgets. Zur Veranschaulichung ergänzen Sie Ihren Code um ein Text-Widget als Kind.
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
body: Container(
color: Colors.white,
child: Text('Huhu')),
),
);
}
}
Je nach Simulator und Gerät lässt sich der Text des Container-Widget kaum erkennen.
Wie können Sie sicherstellen, dass die Inhalte trotz angrenzender Bereiche sauber dargestellt werden? Hier bietet das SafeArea-Widget Abhilfe. Der Code nach body wird in eine SafeArea-Widget integriert.
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: Container(
color: Colors.white,
child: Text('Huhu')),
)),
);
}
}
Sobald Sie das Projekt sichern, rückt der Container mit dem Text-Widget in den von Benutzer:innen ersichtlichen Bereich.
Was kann man mit einem Container-Widget sonst noch machen? Sie können z.B. die Parameter height (Höhe) und width (Breite) anpassen.
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: Container(
height: 100,
width: 100,
color: Colors.white,
child: Text('Huhu')),
)),
);
}
}
Dann besitzen Sie einen Container-Widget mit einer Höhe und Breite von je 100 Pixel.
Wenn Sie das Container-Widget vom Bildschirmrand weg befördern möchten, ist der margin-Parameter nützlich. Mit margin definiert man den Abstand vom Bildschirmrand zur Aussenseite des Container-Widgets. Über EdgeInsets.all(20) fügt man dem Container von jeder Seite einen Rand von je 20 Pixel zu.
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: Container(
height: 100,
width: 100,
margin: EdgeInsets.all(20),
color: Colors.white,
child: Text('Huhu')),
)),
);
}
}
Übung
EdgeInsets Methoden ausprobieren
Testen Sie für den Parameter EdgeInsets was die Methoden symmetric(...), fromLTRB(...) und only(...) genau bewirken. Ein Aufruf von symmetric würde z.B. folgendermassen aussehen:
margin: EdgeInsets.symmetric(vertical: 50, horizontal: 10),
Hilfslinien einblenden
Beim Erstellen von Benutzeroberflächen ist es hilfreich, wenn man über den Flutter Widget Inspector die Hilfslinien einblendet. So kann man sicherstellen, ob sich Widgets in dem von Benutzer:innen ersichtlichen Bereich befinden. Gehen Sie dazu wie folgt vor:
- Wählen Sie in der Kommandoleiste den Flutter Widget Inspector aus.
- Klicken Sie auf den Button mit den Hilfslinien.
- Anschliessend sehen Sie die Hilfslinien im Simulator.
Padding
Um den Inhalt innerhalb des Container-Widgets zu verschieben (hier z.B. das Text-Widget innerhalb der Box) können Sie von dem padding (dt. Füllung) Parameter Gebrauch machen. Auch für den padding Parameter gibt es die EdgeInsets-Methode. Über padding: EdgeInsets.all(20) lässt sich z.B. innerhalb des Container-Widgets eine Polsterung von 20 Pixel einfü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: Container(
height: 100,
width: 100,
margin: EdgeInsets.all(20),
padding: EdgeInsets.all(20),
color: Colors.white,
child: Text('Huhu')),
)),
);
}
}
Hinweis
Margin vs. Padding
Mit margin definiert man um wieviele Pixel die Aussenseite des Container-Widgets vom Bildschirmrand entfernt sein soll. Und mit padding bestimmt man um wieviele Pixel ein Widget von der Innenseite eines Container-Widgets entfernt sein soll.
Zur Erinnerung: ein Container-Widget kann maximal ein Kind (also ein child-Widget) aufnehmen. Im nächsten Abschnitt schauen Sie sich das Column-Widget und sein naher Verwandter das Row-Widget im Detail an. Diese beiden Widgets erlauben nämlich die Integration von mehreren child-Widgets.