一统天下 flutter - 路由和导航: PageRouteBuilder - 路由跳转动画

源码 https://github.com/webabcd/flutter_demo
作者 webabcd

一统天下 flutter - 路由和导航: PageRouteBuilder - 路由跳转动画

示例如下:

lib\route\page_route_builder.dart

/*
 * PageRouteBuilder - 路由跳转动画
 *
 * 本例用于演示如何通过 Navigator 去 push 一个 PageRouteBuilder,从而实现转场动画
 * 如果需要通过 pushNamed() 实现转场动画的话,请参见 page_route_builder2.dart
 */

import 'package:flutter/material.dart';
import 'package:flutter_demo/helper.dart';

class PageRouteBuilderDemo extends StatelessWidget {
  const PageRouteBuilderDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: _Page1(),
    );
  }
}

class _Page1 extends StatelessWidget {
  const _Page1({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("page 1"),
      ),
      backgroundColor: Colors.red,
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            MyButton(
              onPressed: () {
                /// 通过 Navigator 可以 push 一个 PageRouteBuilder
                Navigator.of(context).push(
                    PageRouteBuilder(
                        /// 需要跳转到的页面
                        pageBuilder: (context, animation, secondaryAnimation) => const _Page2(),
                        /// 正向动画时长
                        transitionDuration: const Duration(milliseconds: 2000),
                        /// 反向动画时长
                        reverseTransitionDuration: const Duration(milliseconds: 2000),
                        /// 创建一个 Transition 动画
                        transitionsBuilder: (context, animation, secondaryAnimation, child) {
                          /// 以本例为例对 animation 和 secondaryAnimation 做说明:
                          /// 1、当 push 了 _Page2 时,则 _Page2 做 animation 正向动画
                          /// 2、如果当前显示的是 _Page2,当你 pop 了这个 _Page2 时,则这个 _Page2 会做 animation 反向动画
                          /// 3、如果当前显示的是 _Page2,当你 push 了其他页的时候,则这个 _Page2 会做 secondaryAnimation 正向动画
                          /// 4、如果 _Page2 是路由栈中从栈顶开始数的第 2 个路由,则栈顶 pop 后,这个 _Page2 会做 secondaryAnimation 反向动画
                          return SlideTransition(
                            position: Tween<Offset>(begin: const Offset(1.0, 1.0), end: Offset.zero,).chain(CurveTween(curve: Curves.ease)).animate(animation),
                            child: SlideTransition(
                              position: Tween<Offset>(begin: Offset.zero, end: const Offset(-1.0, 0.0),).chain(CurveTween(curve: Curves.ease)).animate(secondaryAnimation),
                              child: child,
                            ),
                          );
                        }
                    )
                );
              },
              child: const Text('跳转到 page 2'),
            ),
          ],
        )
      ),
    );
  }
}

class _Page2 extends StatelessWidget {
  const _Page2({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("page 2"),
      ),
      backgroundColor: Colors.green,
      body: Center(
        child: MyButton(
          onPressed: () {
            /// 通过继承 PageRouteBuilder 的方式实现路由跳转动画
            Navigator.of(context).push(_MyPageRouteBuilder(const _Page3()));
          },
          child: const Text('跳转到 page 3'),
        ),
      ),
    );
  }
}

class _Page3 extends StatelessWidget {
  const _Page3({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("page 3"),
      ),
      backgroundColor: Colors.blue,
      body: null,
    );
  }
}


/// 封装一个自定义的 PageRouteBuilder(这样可以方便复用)
class _MyPageRouteBuilder extends PageRouteBuilder {

  final Widget widget;

  _MyPageRouteBuilder(this.widget)
      : super(
      transitionDuration: const Duration(milliseconds: 2000),
      reverseTransitionDuration: const Duration(milliseconds: 2000),
      pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
        return widget;
      },
      transitionsBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
        return ScaleTransition(
          scale: animation.drive(Tween<double>(begin: 0.0, end: 1.0).chain(CurveTween(curve: Curves.ease))),
          child: child,
        );
      }
  );
}

源码 https://github.com/webabcd/flutter_demo
作者 webabcd

posted @ 2023-03-22 11:05  webabcd  阅读(94)  评论(0编辑  收藏  举报