阅读 946

flutter中的路由过场动画 PageTransitionsTheme

过场动画

过场动画也就是切换路由时的动画

这个东西有几种方案可以做

  1. 继承 PageRoute来做, 复写 5 个抽象方法, 并抽象buildTransitions
  2. 继承已有的系统类, 比如 MaterialPageRoute 或者 CupertinoPageRoute
  3. 一劳永逸的方案, 使用PageTransitionsTheme类结合 MaterialApp 的 theme 的pageTransitionsTheme属性

前两种目前网络上也有一些人做了分享, 但第三种好像很少有人使用, 我这里就来说一下PageTransitionsTheme的用法

这东西有如下的好处:

  1. 设置一次, 你所有的MaterialPageRoute都可以生效
  2. 对于命名路由, 也就是pushNamed体系的也有效

先分析下源码

为啥分析源码? 因为如果上来就用显得不高端

先找一个大家都知道的切入点, 一般的过场动画都是用的 Navigator.push 方法来实现的

image

看看方法里的实现, 会发现很多常见的东西, 比如, 每一个 Route 都有自己的 OverlayEntry

然后会有一个 install 方法

image

而实际调用中, 这个 Overlay 会被插入到 Overlay 栈内, 从而在界面上显示

image

image

image

image

经过这一串的调用, 就把 Navigator push 和 Route 关联到了一起, 那么 theme 是怎么和 Route 关联起来的呢, 我们进入 MaterialPageRoute 看一下

image

我们看到, 这里是从 Theme 中找到 pageTransitionsTheme, 然后调用 pageTransitionsTheme 的 buildTransitions 方法来完成构建, 所以这就是我们可以在 theme 中一次修改, 多处生效的主因了

如何使用

前面查看到了源码是如何关联到 pageTransitionsTheme 属性的, 我们接着就是该自定义的时候了

修改自己的 MyApp, 修改pageTransitionsTheme属性


class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        pageTransitionsTheme: PageTransitionsTheme(
          builders: <TargetPlatform, PageTransitionsBuilder>{
            TargetPlatform.iOS: createTransition(),
            TargetPlatform.android: createTransition(),
          },
        ),
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

复制代码

使用系统提供的一些动画


PageTransitionsBuilder createTransition() {
  return FadeUpwardsPageTransitionsBuilder();
}

复制代码

效果如下:

image

根据注释, sdk 中有如下几种动画

image

其中FadeUpwardsPageTransitionsBuilder对应安卓默认的, PageTransitionsBuilder自然是对应的 iOS

ZoomPageTransitionsBuilder:

image

OpenUpwardsPageTransitionsBuilder:

image

自定义

除了已有的, 我们还可以自定义动画, 可以配合 animation组件来完成酷炫的动画效果, 具体的可以查看官网动画部分介绍

自定义 MyPageTransitionsBuilder

import 'package:flutter/material.dart';

PageTransitionsBuilder createTransition() {
  // return FadeUpwardsPageTransitionsBuilder();
  // return OpenUpwardsPageTransitionsBuilder();
  // return ZoomPageTransitionsBuilder();
  return MyPageTransitionsBuilder();
}

class MyPageTransitionsBuilder extends PageTransitionsBuilder {
  @override
  Widget buildTransitions<T>(
      PageRoute<T> route,
      BuildContext context,
      Animation<double> animation,
      Animation<double> secondaryAnimation,
      Widget child) {
    return ScaleTransition(
      scale: animation,
      child: RotationTransition(
        turns: animation,
        child: child,
      ),
    );
  }
}
复制代码

效果如下

image

后记

仓库地址

有问题请在本人博客下留言(github 登陆即可)