Все, что вам нужно знать о маршрутизации между страницами Flutter
Будущих учащихся на курсе «Flutter Mobile Developer» и всех интересующихся приглашаем записаться на открытый онлайн-урок по теме «Графика во Flutter». На уроке участники вместе с экспертом-ведущим разберут, как устроен рендеринг во Flutter и изучат основные компоненты библиотеки
dart:ui
.
А сейчас делимся с вами традиционным переводом интересного материала.
Мы знаем, как легко перемещаться с одной страницы на другую во Flutter, используя Navigator. Нам нужно положить в стеке необходимый маршрут для открытия страницы, или извлечь его из стека для ее закрытия.
Открыть страницу по маршруту:
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
Закрыть текущую страницу:
Navigator.pop(context);
Вот так. Но… Это очень скучно, нет никакой анимации.
В Winkl, когда мы начали экспериментировать с анимацией, то поняли, что переход с одной страницы на другую может сделать ваш пользовательский интерфейс действительно красивым. Если вы хотите получить слайд-переход, такой же как в IOS, вы используете CupertinoPageRoute
. Вот и все, ничего больше.
Navigator.push(
context, CupertinoPageRoute(builder: (context) => Screen2()))
Но для пользовательской настройки перемещения Flutter предоставляет различные виджеты этого типа. Давайте посмотрим, как мы можем их использовать.
Мы знаем, что Navigator.push
использует два аргумента (BuildContext context, Route<T> route). Мы можем создать свой собственный маршрут перехода по страницам с некоторой анимацией. Давайте начнем с чего-нибудь простого, вроде слайд-перехода.
Слайд-переход (Slide Transition)
Мы дополним PageRouteBuilder
и установим параметр transitionBuilder
- в результате получаем виджет слайд-перехода (SlideTransition
). Виджет SlideTransition
использует позицию типа Animation <Offset>
. Мы будем использовать значение Tween <Offset>
для задания начального и конечного положения .
import 'package:flutter/material.dart';
class SlideRightRoute extends PageRouteBuilder {
final Widget page;
SlideRightRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
SlideTransition(
position: Tween<Offset>(
begin: const Offset(-1, 0),
end: Offset.zero,
).animate(animation),
child: child,
),
);
}
Теперь мы можем использовать SlideRightRoute
вместо MaterialPageRoute
вот так.
Navigator.push(context, SlideRightRoute(page: Screen2()))
Довольно просто, не так ли? Вы можете изменить направление слайд-перехода, изменив значение смещения.
Масштабирование перехода (Scale Transition)
Scale Transition анимирует масштаб преобразованного виджета. Вы также можете изменить способ анимации, изменив кривые CurvedAnimation
. В приведенном ниже примере я использовал Curves.fastOutSlowIn
.
import 'package:flutter/material.dart';
class ScaleRoute extends PageRouteBuilder {
final Widget page;
ScaleRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
ScaleTransition(
scale: Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.fastOutSlowIn,
),
),
child: child,
),
);
}
Переход с вращением (Rotation Transition)
Такой переход позволяет осуществить вращение в виджете. Вы также можете включить параметр transitionDuration
в ваш виджет PageRouteBuilder
.
import 'package:flutter/material.dart';
class RotationRoute extends PageRouteBuilder {
final Widget page;
RotationRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionDuration: Duration(seconds: 1),
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
RotationTransition(
turns: Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.linear,
),
),
child: child,
),
);
}
Переход с изменением размера (Size Transition)
import 'package:flutter/material.dart';
class SizeRoute extends PageRouteBuilder {
final Widget page;
SizeRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
Align(
child: SizeTransition(
sizeFactor: animation,
child: child,
),
),
);
}
Постепенный переход (Fade Transition)
import 'package:flutter/material.dart';
class FadeRoute extends PageRouteBuilder {
final Widget page;
FadeRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
FadeTransition(
opacity: animation,
child: child,
),
);
}
Здорово! Мы видели все основные переходы.
Теперь давайте сделаем что-нибудь более продвинутое. Что если мы хотим анимировать оба маршрута. Маршрут входа (новая страница) и маршрут выхода (старая страница). Мы можем использовать анимации переноса в стек и применять их к обоим маршрутам. Одним из примеров может быть слайд-смещение по новому и старому маршрутам. Это моя любимая анимация перехода ❤️. Давайте посмотрим, как это сделать.
import 'package:flutter/material.dart';
class EnterExitRoute extends PageRouteBuilder {
final Widget enterPage;
final Widget exitPage;
EnterExitRoute({this.exitPage, this.enterPage})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
enterPage,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
Stack(
children: <Widget>[
SlideTransition(
position: new Tween<Offset>(
begin: const Offset(0.0, 0.0),
end: const Offset(-1.0, 0.0),
).animate(animation),
child: exitPage,
),
SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: enterPage,
)
],
),
);
}
И используйте это так.
Navigator.push(context,
EnterExitRoute(exitPage: this, enterPage: Screen2()))
Мы также можем объединить несколько переходов, чтобы создать нечто удивительное, например, масштабирование и вращение одновременно.
Сначала используется ScaleTransition
(масштабирование), далее - RotationTransition
(вращение), и потом, страница.
import 'package:flutter/material.dart';
class ScaleRotateRoute extends PageRouteBuilder {
final Widget page;
ScaleRotateRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionDuration: Duration(seconds: 1),
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
ScaleTransition(
scale: Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.fastOutSlowIn,
),
),
child: RotationTransition(
turns: Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.linear,
),
),
child: child,
),
),
);
}
Отличная работа, ребята! Это все, что вам нужно знать об анимации маршрута перехода в Flutter. Попробуйте сделать некоторые комбинации с переходами и сделайте что-нибудь великое. Если вы сделаете что-то великое, не забудьте поделиться этим со мной. Весь исходный код здесь на GitHub repo.
Узнать подробнее о курсе «Flutter Mobile Developer».
Записаться на открытый онлайн-урок по теме «Графика во Flutter».