Appearance
Kapitel 8: Routing & Navigation
8.1 Konzept der Routing (Seitennavigation)
Was ist Routing?
Routing = Mechanismus zum Wechseln zwischen Seiten (Screens) in einer App.
In Flutter:
- Jede Seite ist ein
Widget(meistStatelessWidgetoderStatefulWidget) Navigatorverwaltet den Seiten-Stapel (Stack)- Seiten können vorwärts (
push) und rückwärts (pop) navigieren
Navigator-Stack:
[ Seite 1 ] ← Aktuelle Seite (oben)
[ Seite 2 ] ← Vorherige Seite (unten)
[ Seite 3 ] ← Noch weiter unten8.2 Basis-Routing (Navigator)
Navigator.push() (Zu neuer Seite navigieren)
dart
// Seite 1 (Ausgangsseite)
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Seite2()),
);
},
child: const Text('Zu Seite 2'),
)Erklärung:
Navigator.push(): Fügt neue Seite zum Stack hinzuMaterialPageRoute: Animierter Übergang (von rechts für iOS, von unten für Android)builder: Erstellt die neue Seite
Navigator.pop() (Zurück zur vorherigen Seite)
dart
// Seite 2 (neue Seite)
ElevatedButton(
onPressed: () {
Navigator.pop(context); // Entfernt aktuelle Seite vom Stack
},
child: const Text('Zurück'),
)Anwendungsfall:
- ✅ "Zurück"-Button
- ✅ Abbrechen-Button
- ✅ Speichern-Button (nach Speichern zurück)
Daten an vorherige Seite zurückgeben
Seite 1 (Daten erwarten):
dart
ElevatedButton(
onPressed: () async {
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Seite2()),
);
print('Erhalten: $result'); // Verarbeitet zurückgegebene Daten
},
child: const Text('Zu Seite 2 (mit Rückgabe)'),
)Seite 2 (Daten zurückgeben):
dart
ElevatedButton(
onPressed: () {
Navigator.pop(context, 'Hallo von Seite 2'); // Daten zurückgeben
},
child: const Text('Zurück mit Daten'),
)8.3 Benannte Routing (Named Routes - empfohlen für größere Apps)
Warum benannte Routing?
Nachteil von MaterialPageRoute:
- ❌ Seitennamen sind Strings (Tippfehler möglich)
- ❌ Schwer zu warten bei vielen Seiten
- ❌ Keine zentrale Verwaltung
Vorteile von benannten Routing:
- ✅ Zentrale Verwaltung aller Routen
- ✅ Typsicherheit (keine Tippfehler)
- ✅ Bessere Wartbarkeit
Konfiguration (in MaterialApp)
dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Routing Beispiel',
// Routen definieren
routes: {
'/': (context) => const StartSeite(),
'/profil': (context) => const ProfilSeite(),
'/einstellungen': (context) => const EinstellungenSeite(),
},
// Startseite (initiale Route)
initialRoute: '/',
);
}
}Navigator.pushNamed() (Navigation mit Namen)
dart
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/profil');
},
child: const Text('Zu Profil'),
)Routen-Parameter übergeben & empfangen
Methode 1: Über settings (empfohlen)
dart
// In MaterialApp: onGenerateRoute verwenden
MaterialApp(
onGenerateRoute: (settings) {
if (settings.name == '/profil') {
final userId = settings.arguments as String; // Parameter empfangen
return MaterialPageRoute(
builder: (context) => ProfilSeite(userId: userId),
);
}
return null;
},
)Parameter übergeben:
dart
Navigator.pushNamed(
context,
'/profil',
arguments: 'user123', // Parameter übergeben
);Methode 2: Über ModalRoute.of() (innerhalb der Zielseite)
dart
class ProfilSeite extends StatelessWidget {
const ProfilSeite({super.key});
@override
Widget build(BuildContext context) {
// Parameter empfangen
final userId = ModalRoute.of(context)!.settings.arguments as String;
return Scaffold(
appBar: AppBar(title: const Text('Profil')),
body: Center(
child: Text('User ID: $userId'),
),
);
}
}8.4 Routing-Wache (onGenerateRoute - für Berechtigungskontrolle)
Was ist Routing-Wache?
Anwendungsfall: Manche Seiten dürfen nur nach dem Login aufgerufen werden.
Lösung: onGenerateRoute abfangen und auf Berechtigung prüfen.
Implementierung
dart
MaterialApp(
onGenerateRoute: (settings) {
// Beispiel: Login-Status prüfen
final isLoggedIn = false; // In echt: aus Provider/SharedPreferences
// Geschützte Routen
if (settings.name == '/profil' || settings.name == '/einstellungen') {
if (!isLoggedIn) {
// Nicht eingeloggt → Zu Login-Seite weiterleiten
return MaterialPageRoute(builder: (context) => const LoginSeite());
}
}
// Normale Routing
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (context) => const StartSeite());
case '/profil':
return MaterialPageRoute(builder: (context) => const ProfilSeite());
case '/login':
return MaterialPageRoute(builder: (context) => const LoginSeite());
default:
return MaterialPageRoute(builder: (context) => const NotFoundSeite());
}
},
)8.5 Seitenübergangs-Animation (benutzerdefiniert)
Standard-Animation überschreiben
dart
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => const ZielSeite(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
// Benutzerdefinierte Animation
var begin = const Offset(1.0, 0.0); // Von rechts
var end = Offset.zero;
var curve = Curves.ease;
var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
return SlideTransition(
position: animation.drive(tween),
child: child,
);
},
),
);Häufige Animationen
1. Fade-Animation (Einblenden)
dart
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(opacity: animation, child: child);
}2. Scale-Animation (Vergrößern)
dart
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return ScaleTransition(scale: animation, child: child);
}3. Rotation-Animation (Drehen)
dart
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return RotationTransition(turns: animation, child: child);
}8.6 Praxisbeispiel: Multi-Seiten-App mit Routing
Schritt 1: Seiten erstellen
dart
// StartSeite
class StartSeite extends StatelessWidget {
const StartSeite({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Startseite')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/profil');
},
child: const Text('Zu Profil'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/einstellungen');
},
child: const Text('Zu Einstellungen'),
),
],
),
),
);
}
}
// ProfilSeite
class ProfilSeite extends StatelessWidget {
const ProfilSeite({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Profil')),
body: const Center(
child: Text('Dies ist die Profil-Seite', style: TextStyle(fontSize: 24)),
),
);
}
}
// Einstellungen-Seite
class EinstellungenSeite extends StatelessWidget {
const EinstellungenSeite({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Einstellungen')),
body: const Center(
child: Text('Dies ist die Einstellungen-Seite', style: TextStyle(fontSize: 24)),
),
);
}
}Schritt 2: In main.dart Routen konfigurieren
dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Routing Beispiel',
routes: {
'/': (context) => const StartSeite(),
'/profil': (context) => const ProfilSeite(),
'/einstellungen': (context) => const EinstellungenSeite(),
},
initialRoute: '/',
);
}
}Schritt 3: App ausführen und testen
bash
flutter runSie sollten:
- Startseite sehen
- Auf "Zu Profil" klicken → Profil-Seite öffnet sich
- Auf "Zurück" (Android Back-Button oder AppBar-Pfeil) klicken → Zurück zur Startseite
- Auf "Zu Einstellungen" klicken → Einstellungen-Seite öffnet sich
Zusammenfassung
In diesem Kapitel haben Sie:
- ✅ Das Konzept der Routing (Seitennavigation) verstanden
- ✅ Basis-Routing mit
Navigator.push()undNavigator.pop()gemeistert - ✅ Daten zwischen Seiten übergeben und empfangen
- ✅ Benannte Routing (
routes,pushNamed) für größere Apps implementiert - ✅ Routing-Wache (
onGenerateRoute) für Berechtigungskontrolle erstellt - ✅ Benutzerdefinierte Seitenübergangs-Animationen erstellt
- ✅ Ein Praxisbeispiel (Multi-Seiten-App) implementiert
Nächstes Kapitel: Wir werden Netzwerkrequests lernen (Dio, GET/POST, JSON-Parsing).
Übungsaufgaben:
- Erstellen Sie eine 3-Seiten-App (Start, Über uns, Kontakt) mit benannten Routing
- Implementieren Sie eine Login-Seite, die nach erfolgreichem Login zur Profil-Seite navigiert
- Übergeben Sie einen Benutzernamen von der Login-Seite zur Profil-Seite
- Erstellen Sie eine benutzerdefinierte Seitenübergangs-Animation (Fade oder Scale)
- Implementieren Sie eine Routing-Wache, die unautorisierte Zugriffe auf geschützte Seiten verhindert
Häufige Fehler:
- ❌
Navigator.push()ohneMaterialPageRouteverwenden → Animation fehlt - ❌
Navigator.pop()auf der Startseite aufrufen → App schließt (oder Fehler) - ❌ Routen-Namen falsch schreiben (Tippfehler) →
Navigator.pushNamed()findet keine Route - ❌ Parameter übergeben, aber in Zielseite nicht empfangen →
NullPointerException
