[Перевод] Все, что вам нужно знать о переходе с 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».


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

Let’s block ads! (Why?)

Read More

Recent Posts

Российская «дочка» Google подготовила 23 иска к крупнейшим игрокам рекламного рынка

Конкурсный управляющий российской «дочки» Google подготовил 23 иска к участникам рекламного рынка. Общая сумма исков составляет 16 млрд рублей –…

1 час ago

Google завершил обновление основного алгоритма March 2024 Core Update

Google завершил обновление основного алгоритма March 2024 Core Update. Раскатка обновлений была завершена 19 апреля, но сообщил об этом поисковик…

4 часа ago

Нейросети будут писать тексты объявления за продавцов на Авито

У частных продавцов на Авито появилась возможность составлять текст объявлений с помощью нейросети. Новый функционал доступен в категории «Обувь, одежда,…

5 часов ago

Объявлены победители международной премии Workspace Digital Awards-2024

24 апреля 2024 года в Москве состоялась церемония вручения наград международного конкурса Workspace Digital Awards. В этом году участниками стали…

18 часов ago

Яндекс проведет гик-фестиваль Young Con

27 июня Яндекс проведет гик-фестиваль Young Con для студентов и молодых специалистов, которые интересуются технологиями и хотят работать в IT.…

1 день ago

Деньги дороже свободы: Telegram ограничивает доступ к некоторым каналам по требованию Apple

Павел Дуров сообщил, что Telegram начнет цензурировать контент по требованию Apple. В противном случае приложение Telegram может быть удалено из…

2 дня ago