betacode

Navigation и Routing в Flutter

  1. Route Transition
  2. Named Route

1. Route Transition

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
      );
    },
  );
}
  • Руководство Flutter SlideTransition
  • Руководство Flutter ScaleTransition

2. Named Route

В 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");

Pуководства Flutter

Show More