Все, что вам нужно знать о переходе с Flutter страницы

от автора

Будущих учащихся на курсе «Flutter Mobile Developer» и всех интересующихся приглашаем записаться на открытый онлайн-урок по теме «Графика во Flutter». На уроке участники вместе с экспертом-ведущим разберут, как устроен рендеринг во Flutter и изучат основные компоненты библиотеки dart:ui.

А сейчас делимся с вами традиционным переводом интересного материала.


Мы знаем, как легко перемещаться с одного маршрута на другой в Flutter. Нам просто нужно добавить и вытащить.

Добавить:

Navigator.push(     context,     MaterialPageRoute(builder: (context) => SecondRoute()),   );

Вытащить:

Navigator.pop(context);

Вот так. Но это скучновато, нет никакой анимации на сайте

В Winkl, когда мы начали играть с анимацией, мы поняли, что переход на страницу может действительно сделать ваш пользовательский интерфейс красивым. Если вы хотите иметь слайд-переход, как IOS вы используете CupertinoPageRoute. Вот и все, ничего больше.

Но для пользовательского перехода Flutter предоставляет различные виджеты перехода. Давайте посмотрим, как мы можем их использовать.

Мы знаем, что Navigator.push принимает два аргумента (BuildContext context, Route<T> route). Мы можем создать свой собственный маршрут страницы с некоторой анимацией перехода. Давайте начнем с чего-нибудь простого, вроде слайд-перехода.

Слайд-переход

Мы расширим 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()))

Результат:

Довольно просто, не так ли? Вы можете изменить направление слайд-перехода, изменив смещение.

Переход масштаба

Переход масштаба анимирует масштаб преобразованного виджета. Вы также можете изменить способ анимации, изменив кривые 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,               ),         ); }

Результат:

Ротационный переход

Ротационный переход анимирует ротацию виджета. Вы также можете предоставить 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,               ),         ); }

Результат:

Размерный переход

Подробнее

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,                 ),               ),         ); }

Результат:

Теневой переход

Подробнее

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. Связаться со мной можно в Twitter, Github и LinkedIn.


Узнать подробнее о курсе «Flutter Mobile Developer».

Записаться на открытый онлайн-урок по теме «Графика во Flutter».


ЗАБРАТЬ СКИДКУ

ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/539190/