3.4 Benutzerdefinierte Schriften und Icons (freiwillig)
Benutzerdefinierte Schrift verwenden
Falls Sie mit der Standardschrift nicht zufrieden sind, gibt es auch die Möglichkeit benutzerdefinierten Schriftarten in das Flutter-Projekt zu integrieren. Als erstes müssen Sie dazu eine andere Schriftart herunterladen. Das geht am einfachsten über die Webseite fonts.google.com, da dort alle Schriften für die kommerzielle Nutzung kostenlos sind. Die Schrift, welche wir für unsere Visitenkarten-App verwenden werden, heisst Pacifico.
Um Pacifico herunterzuladen, wählen Sie diese Schriftart aus und klicken anschliessend auf die Schaltfläche Download family.
Sobald Sie Pacifico heruntergeladen haben, erscheint in Ihrem Downloads-Verzeichnis eine Datei mit dem Namen Pacifico.zip. Entpacken Sie dieses Zip-Archiv. Der Inhalt sollte aus folgenden zwei Dateien bestehen.
Wechseln Sie zu Ihrem Flutter-Projekt in VS Code und erstellen Sie analog wie das assets-Verzeichnis bei der Rezept-App auf der obersten Ebene Ihres Projekts ein Ordner mit der Bezeichnung fonts. Sobald Sie das fonts-Verzeichnis angelegt haben, ziehen Sie aus Ihrem entzippten Pacifico Ordner die Datei Pacifico-Regular.ttf per Drag-and-Drop in das fonts-Verzeichnis. Nach erfolgreichem Import müsste die Schrift unterhalb des fonts-Verzeichnis erscheinen.
Damit Ihre Flutter-App auf diese Schrift zugreifen kann, müssen Sie wieder die pubspec.yaml Datei anpassen. Klicken Sie in der Seitenleiste auf pubspec.yaml (1) und scrollen Sie in dieser Datei zu dem Teil, wo erklärt wird, wie Sie fonts zu Ihrem Projekt hinzufügen können (2).
Löschen Sie diesen Code und ersetzen Sie ihn durch:
fonts:
- family: Pacifico
fonts:
- asset: fonts/Pacifico-Regular.ttf
Wechseln Sie wieder zurück auf Ihre main.dart Datei und erweitern Sie dort die style-Eigenschaft um die neue Schriftfamilie (fontFamily: 'Pacifico').
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: [
CircleAvatar(
radius: 50.0,
backgroundImage: AssetImage('assets/grumpy_cat.jpg'),
),
Text(
'Grumpy Cat',
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 40,
color: Colors.white,
fontWeight: FontWeight.bold,
),
)
],
)),
),
);
}
}
Da Sie eine neue Ressource in Form einer Schriftfamilie zum Flutter-Projekt hinzugefügt haben, reicht hier ein Hot-Reload nicht aus, um die Änderungen direkt im Simulator zu verfolgen. Sie müssen den iOS- oder Android-Simulator zuerst über das Stopp-Icon beenden (1) und dann über das Start-Icon (2) erneut starten.
Ihr Profilbild sollte nun von einer viel hübscheren Schrift umgeben sein.
Übung
Rolle in Visitenkarten-App integrieren
Als Übung können Sie das gerade Gelernte anwenden und den nächsten Teil der Visitenkarten-App erstellen, wo Sie Ihre Rolle beschreiben. Der Text für Ihre Rolle sollte unterhalb von Ihrem Namen in Grossbuchstaben erscheinen. Verwenden Sie dafür die Schriftart Source Sans Pro, welche Sie ebenfalls auf fonts.google.com finden. Aus dem Zip-Archiv müssen Sie nur die Datei SourceSansPro-Regular.ttf in das Flutter-Projekt importieren.
Lösung
Die Visitenkarten-App beinhaltet jetzt ein Profilbild und eine Rolle.
Jetzt fehlen uns in der Visitenkarten-App nur noch die kleinen Boxen mit der Telefonnummer und E-Mail-Adresse. Für die Icons der Boxen könnte man ein Bild als Icon verwenden. Aber die Verwendung von Icon-Widgets lässt hier mehr Flexibilität zu. Unser Column-Widget besteht an diesem Punkt aus einem CircleAvatar-Widget für unser Profilbild und zwei Text-Widgets zur Darstellung unseres Namens und unserer Rolle.
Theorie
Bilder vs. Icons
Ein Bild wird einfach so angezeigt, wie es ist und es verpixelt ab einer bestimmten Grösse (Rastergrafik). Für ein Icon werden hingegen alle Seiten und Kanten immer frisch auf den Bildschirm gezeichnet (Vektorgrafik). So lässt sich beispielsweise die Farbe des Icons oder die Grösse des Icons im Handumdrehen ändern.
Mit dem material.dart-Paket von Flutter besitzen wir bereits Zugriff auf eine ganze Reihe von Icons. Auf der Webseite https://fonts.google.com/icons kann man nach spezifischen Icons suchen. In unserer Visitenkarten-App möchten wir die Telefonnummer mit einem Telefon-Icon ergänzen. Also suchen wir auf der Icon-Webseite von Google nach ‘phone’ (1). Sobald man das gewünschte Icon gefunden hat (2), kann man in der Seitenleiste Flutter auswählen (3) und es erscheint der Dart-Code (4) um dieses Icon in eine Flutter-App einzubetten.
Icons hinzufügen
Zuerst fügen wir als child-Widget ein Container-Widget ein, welches wiederum ein Row-Widget als Kind besitzt. Sehr oft werden Sie beim Erstellen von Benutzeroberflächen in Flutter-Apps feststellen, dass Sie Row-Widgets in Column-Widgets oder Column-Widgets in Row-Widgets einbetten. So erhält man ein Art Raster, welches die Layout-Gestaltung sehr flexibel macht. Unser Row-Widget wird eine Menge von verschiedenen child-Widgets erhalten und das erste Kind beinhaltet eine Instanz aus der Icon-Klasse. Nachfolgend der Code zum Einbetten eines Telefon-Icons.
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: [
CircleAvatar(
radius: 50.0,
backgroundImage: AssetImage('assets/grumpy_cat.jpg'),
),
Text(
'Grumpy Cat',
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 40,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
Text(
'GUTE LAUNE VERBREITER',
style: TextStyle(
fontFamily: 'Source Sans Pro',
color: Colors.lightBlue.shade100,
fontSize: 20,
letterSpacing: 2.5,
fontWeight: FontWeight.bold,
),
),
Container(
child: Row(
children: [
Icon(
Icons.phone_outlined,
),
],
),
)
],
)),
),
);
}
}
Nach einem Hot-Reload können Sie das Telefon-Icon in der App sehen. Die Verwendung von Icons macht vor allem dann Sinn, wenn Sie nicht viel Zeit damit verbringen möchten, Designelemente zu finden, selber zu erstellen oder dafür zu bezahlen.
In der Theoriebox haben wir erwähnt, dass Icons besser sind als Bilder, weil sie im Handumdrehen gezeichnet werden können. Wir können das Telefon-Icon zum Beispiel in ein viel grösseres Icon verwandeln, indem wir einfach seine size-Eigenschaft ändern.
Icon(
Icons.phone_outlined,
size: 100,
),
Oder bei Icons besitzen wir auch die Möglichkeit, direkt die Farbe zu verändern.
Icon(
Icons.phone_outlined,
size: 100,
color: Colors.lightBlue.shade900,
),
Telefonnummer hinzufügen
Zusätzlich zum Telefon-Icon möchten wir in unserer Visitenkarten-App auch noch eine Telefonnummer darstellen, also benötigen wir in unserem Container zusätzlich ein Text-Widget mit der gewünschten Telefonnummer als String. Diesen Text stylen wir etwas um, da da das Standardlayout etwas gar langweilig daherkommt.
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: [
CircleAvatar(
radius: 50.0,
backgroundImage: AssetImage('assets/grumpy_cat.jpg'),
),
Text(
'Grumpy Cat',
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 40,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
Text(
'GUTE LAUNE VERBREITER',
style: TextStyle(
fontFamily: 'Source Sans Pro',
color: Colors.lightBlue.shade100,
fontSize: 20,
letterSpacing: 2.5,
fontWeight: FontWeight.bold,
),
),
Container(
child: Row(
children: [
Icon(
Icons.phone_outlined,
color: Colors.lightBlue.shade900,
),
Text(
'+41 777 77 77',
style: TextStyle(
color: Colors.lightBlue.shade900,
fontFamily: 'Source Sans Pro',
fontSize: 20,
),
)
],
),
)
],
)),
),
);
}
}
Das sieht schon ziemlich gut aus, aber es wäre schön, wenn zwischen dem Telefon-Icon und dem Text etwas mehr Platz wäre. Unser Icon und Text befindet sich in einem Row-Widget, also lässt sich mit Hilfe einer SizedBox Platz zwischen den child-Widgets schaffen. Falls Sie sich im Umgang mit SizedBox-Widgets nicht mehr sicher fühlen, können Sie nochmals den Abschnitt 3.2 bearbeiten. Wir integrieren ein SizedBox-Widget in unsere App. Zusätzlich verpassen wir unserem Container eine weisse Farbe und Seitenränder, damit er sich besser von den anderen Widgets abgrenzt.
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: [
CircleAvatar(
radius: 50.0,
backgroundImage: AssetImage('assets/grumpy_cat.jpg'),
),
Text(
'Grumpy Cat',
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 40,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
Text(
'GUTE LAUNE VERBREITER',
style: TextStyle(
fontFamily: 'Source Sans Pro',
color: Colors.lightBlue.shade100,
fontSize: 20,
letterSpacing: 2.5,
fontWeight: FontWeight.bold,
),
),
Container(
color: Colors.white,
margin: EdgeInsets.symmetric(vertical: 10, horizontal: 25),
child: Row(
children: [
Icon(
Icons.phone_outlined,
color: Colors.lightBlue.shade900,
),
SizedBox(
width: 10,
),
Text(
'+41 777 77 77',
style: TextStyle(
color: Colors.lightBlue.shade900,
fontFamily: 'Source Sans Pro',
fontSize: 20,
),
)
],
),
)
],
)),
),
);
}
}
Jetzt können Sie sehen, dass unser Container-Widget ein wenig weiter vom Bildschirmrand entfernt ist. Über den padding Parameter können wir zusätzlich den weissen Rahmen um den Text etwas vergrössern.
Container(
color: Colors.white,
margin: EdgeInsets.symmetric(vertical: 10, horizontal: 25),
padding: EdgeInsets.all(10),
child: Row(
Übung
Weiteres Icon und Text-Widget hinzufügen
Erstellen Sie den zweiten Container mit dem E-Mail-Icon und Ihrer E-Mail-Adresse. Nutzen Sie dazu das, was Sie in diesem Abschnitt gelernt haben und auch die Flutter-Dokumentation. Das zweite Container-Widget folgt im Quellcode gleich nach dem ersten, also scrollen Sie im Code bis zur schliessenden Klammer des ersten Container-Widgets, fügen dort ein Komma und den Inhalt des ersten Container-Widgets als Ausgangspunkt ein. Ersetzen Sie im zweiten Container-Widget das Telefon-Icon durch ein E-Mail-Icon und passen Sie den Inhalt des Strings an, welcher die Telefonnummer beinhaltet.
Lösung
Im nächsten Abschnitt werden wir unsere Beispiel Visitenkarten-App fertigstellen und die Textboxen mit dem Card-Widget ein wenig schöner aussehen lassen.