Будущих учащихся на курсе «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».
