Flutter-Navigation und Routing

Dieser Abschnitt stellt die Navigations- und Routing-Mechanismen in Flutter vor, einschließlich Seitenübergängen, Parameterübergabe und benannten Routen.


Navigator-Grundlagen

Flutter verwendet Navigator für die Seitenverwaltung und implementiert Seitenübergänge basierend auf einer Stapelstruktur.

Beispiel: Grundlegende Seitennavigation

// Zu einer neuen Seite navigieren
Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => const DetailPage(),
  ),
);

// Zurück zur vorherigen Seite
Navigator.of(context).pop();

// Mit Ergebnis zurückkehren
Navigator.of(context).pop('Returned data');

// Aktuelle Seite ersetzen (keine Rückkehr möglich)
Navigator.of(context).pushReplacement(
  MaterialPageRoute(
    builder: (context) => const HomePage(),
  ),
);

// Zur Wurzelseite zurückkehren
Navigator.of(context).popUntil((route) => route.isFirst);

MaterialPageRoute vs CupertinoPageRoute

Beispiel: Seitenübergangsanimationen auf verschiedenen Plattformen

// Android-Stil - steigt von unten auf
Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => const DetailPage(),
  ),
);

// iOS-Stil - gleitet von rechts herein
Navigator.of(context).push(
  CupertinoPageRoute(
    builder: (context) => const DetailPage(),
  ),
);

// Benutzerdefinierter Übergangseffekt
Navigator.of(context).push(
  PageRouteBuilder(
    pageBuilder: (context, animation, secondaryAnimation) {
      return const DetailPage();
    },
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      // Ein-/Ausblendeffekt
      return FadeTransition(
        opacity: animation,
        child: child,
      );
    },
    transitionDuration: const Duration(milliseconds: 300),
  ),
);

Übergeben von Seitenparametern

< h2 class="example">Beispiel: Parameter an eine neue Seite übergeben
// Zur Detailseite springen und Parameter übergeben
Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => ProductDetailPage(productId: 123),
  ),
);

// Detailseite empfängt Parameter
class ProductDetailPage extends StatelessWidget {
  final int productId;

  const ProductDetailPage({
    super.key,
    required this.productId,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Produkt $productId')),
      body: Center(child: Text('Produkt-ID: $productId')),
    );
  }
}

// Mehrere Parameter übergeben
class UserProfilePage extends StatelessWidget {
  final String name;
  final int age;

  const UserProfilePage({
    super.key,
    required this.name,
    required this.age,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(Startseite von $name)),
      body: Center(child: Text('Alter: $age')),
    );
  }
}

// Springen
Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => const UserProfilePage(
      name: 'Zhang San',
      age: 25,
    ),
  ),
);

Benannte Route

Die Verwendung benannter Routen kann die Konfiguration von Seitenübergängen vereinfachen.

Beispiel: Konfiguration benannter Routen

void main() {
  runApp(
    MaterialApp(
      // Routing-Tabelle definieren
      initialRoute: '/',
      routes: {
        '/': (context) => const HomePage(),
        '/detail': (context) => const DetailPage(),
        '/user': (context) => const UserPage(),
        '/settings': (context) => const SettingsPage(),
      },
    ),
  );
}

// Springen
Navigator.pushNamed(context, '/detail');

// Mit Parametern navigieren
Navigator.pushNamed(context, '/user', arguments: {'name': 'Zhang San', 'age': 25});

// Parameter auf der Zielseite abrufen
class DetailPage extends StatelessWidget {
  const DetailPage({super.key});

  @override
  Widget build(BuildContext context) {
    // Die übergebenen Parameter abrufen
    final args = ModalRoute.of(context)?.settings.arguments as Map?;

    return Scaffold(
      appBar: AppBar(title: const Text('Detail Page')),
      body: Center(
        child: Text(Arguments: $args),
      ),
    );
  }
}

Eine andere Möglichkeit, Werte beim Routing zu übergeben

Beispiel: onGenerateRoute

MaterialApp(
  onGenerateRoute: (settings) {
    // Je nach Routenname unterschiedliche Seiten zurückgeben
    switch (settings.name) {
      case '/':
        return MaterialPageRoute(
          builder: (_) => const HomePage(),
        );
      case '/detail':
        // Parameter aus Argumenten abrufen
        final args = settings.arguments as Map<String, dynamic>?;
        return MaterialPageRoute(
          builder: (_) => DetailPage(
            id: args?['id'] ?? 0,
            title: args?['title'] ?? '',
          ),
        );
      case '/product':
        final productId = settings.name?.split('/').last;
        return MaterialPageRoute(
          builder: (_) => ProductPage(id: productId ?? ''),
        );
      default:
        return MaterialPageRoute(
          builder: (_) => const NotFoundPage(),
        );
    }
  },
)

Für einfache Anwendungen ist das grundlegende Navigator.push ausreichend; für mittlere bis große Anwendungen wird empfohlen, benannte Routen oder Routing-Management-Bibliotheken zu verwenden, um Seiten zentral zu verwalten.

Weitere Erweiterungen