Navigation и Routing в Flutter
View more Tutorials:
Flutter вводит понятие "Route Transition" (переход маршрута) для описания действия переключения с первого экрана на второй. Этот переход (transition) может включать в себя анимационный эффект для произведения благоприятного впечатления на пользователей. В этой статье я расскажу о нескольких способах для этого.
Для простоты вы можете взглянуть на иллюстрацию ниже, а затем мы проанализируем, как это сделать:

Сначала пользователь стоит на первой странице (Page1) и выполняет действие, такое как нажатие кнопки для перехода на вторую страницу (Page2), в процессе перехода между двумя страницами может появиться анимационный эффект. Однако в этом простом примере я не создал анимацию.
main.dart (ex 1)
import 'package:flutter/material.dart'; main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'o7planning.org', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: Page1(), ); } } class Page1 extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Title of Page 1"), ), body: Center( child: ElevatedButton( child: Text('Go!'), onPressed: () { Navigator.of(context).push(_createRoute()); }, ), ), ); } } Route _createRoute() { return PageRouteBuilder( pageBuilder: (BuildContext context, Animation<double> animation,// Animation<double> secondaryAnimation) { return Page2(); }, transitionsBuilder: (BuildContext context, Animation<double> animation, // Animation<double> secondaryAnimation, Widget child) { return child; }, ); } class Page2 extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Title of Page 2"), ), body: Center( child: Text('Page 2'), ), backgroundColor: Colors.lightGreen[100], ); } }
Самое важное — это создать объект Route, который описывает, как первая страница будет заменена второй. Класс PageRouteBuilder является классом-потомком Route, который использовался для первого примера благодаря его простоты использования.

_createRoute()
Route _createRoute() { return PageRouteBuilder( pageBuilder: (BuildContext context, Animation<double> animation,// Animation<double> secondaryAnimation) { return Page2(); }, transitionsBuilder: (BuildContext context, Animation<double> animation, // Animation<double> secondaryAnimation, Widget child) { return child; }, ); }
После этого используйте Navigator (навигатор) для выполнения Route (маршрут).
Navigator.of(context).push(_createRoute());
Далее мы добавим анимацию SlideTransition в середине процесса перехода с первой страницы на вторую:
(ex 1b)
Route _createRoute() { return PageRouteBuilder( pageBuilder: (BuildContext context, Animation<double> animation,// Animation<double> secondaryAnimation) { return Page2(); }, transitionsBuilder: (BuildContext context, Animation<double> animation, // Animation<double> secondaryAnimation, Widget child) { return SlideTransition( position: new Tween<Offset>( begin: const Offset(-1.0, 0.0), end: Offset.zero, ).animate(animation), child: new SlideTransition( position: new Tween<Offset>( begin: Offset.zero, end: const Offset(-1.0, 0.0), ).animate(secondaryAnimation), child: child, ), ); }, ); }
Вы получите следующий результат:

Вот еще один пример анимации с ScaleTransition:

(ex 1c)
Route _createRoute() { return PageRouteBuilder( pageBuilder: (BuildContext context, Animation<double> animation,// Animation<double> secondaryAnimation) { return Page2(); }, transitionsBuilder: (BuildContext context, Animation<double> animation, // Animation<double> secondaryAnimation, Widget child) { return new ScaleTransition( scale: new Tween<double>( begin: 0.0, end: 1.0, ).animate( CurvedAnimation( parent: animation, curve: Interval( 0.00, 0.50, curve: Curves.easeInCirc, ), ), ), child: child ); }, ); }
- TODO Link!
- TODO Link!
В Flutter вы также можете определить карту (Map), содержащую основные страницы приложения и соответствующие им названия, а затем использовать Navigator для перемещения на разные страницы на основе этих названий.
Сначала давайте рассмотрим результат примера:

main.dart (ex 4)
import 'package:flutter/material.dart'; main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'o7planning.org', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), initialRoute: '/home', routes: <String, WidgetBuilder>{ '/home': (BuildContext context) => Home(), '/details': (BuildContext context) => Details(), '/about': (BuildContext context) => About(), }, ); } } class Home extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Title of Home Page"), ), body: Center( child: Row ( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ ElevatedButton( child: Text('Go to Details Page'), onPressed: () { Navigator.of(context).pushNamed('/details'); }, ), ElevatedButton( child: Text('Go to About Page'), onPressed: () { Navigator.of(context).pushNamed('/about'); }, ), ], ) ), ); } } class Details extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Title of Details Page"), ), body: Center( child: ElevatedButton( child: Text('Close'), onPressed: () { // Close page and pass a value back to previous page Navigator.of(context).pop(); }, ), ), backgroundColor: Colors.lightGreen[100], ); } } class About extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Title of About Page"), ), body: Center( child: ElevatedButton( child: Text('Close'), onPressed: () { // Close page Navigator.of(context).pop(); }, ), ), backgroundColor: Colors.cyan[100], ); } }
В этом примере мы используем свойство routes из MaterialApp для определения route Map, содержащей основные страницы приложения и соответствующие им названия.
// Map<String, WidgetBuilder> routes MaterialApp( title: 'o7planning.org', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), initialRoute: '/home', routes: <String, WidgetBuilder>{ '/home': (BuildContext context) => Home(), '/details': (BuildContext context) => Details(), '/about': (BuildContext context) => About(), }, );
Затем переходим на разные страницы в зависимости от названия route.
Navigator.of(context).pushNamed('/details');
Или вернуться на предыдущую страницу:
// Close page (Back to previous page) Navigator.of(context).pop(); // Close page and pass a value back to previous page. Navigator.of(context).pop("Some Value");