关于flutter:flutter系列之如何自定义动画路由

简介

flutter中有默认的Route组件,叫做MaterialPageRoute,个别状况下咱们在flutter中进行跳转的话,只须要向Navigator中传入一个MaterialPageRoute就能够了。

然而MaterialPageRoute太普通了,如果咱们想要做点不同的跳转特效应该如何解决呢?

一起来看看吧。

自定义跳转应用

失常状况下,咱们进行路由跳转须要用到Navigator和MaterialPageRoute,如下所示:

 Navigator.push(context, MaterialPageRoute(builder: (context) {
            return const NextPage();

如果要实现特定的路由动画,那么须要进行路由的自定义。

在flutter中也就是要应用PageRouteBuilder来自定义一个Route。

先来看下PageRouteBuilder的定义:

class PageRouteBuilder<T> extends PageRoute<T> {

  PageRouteBuilder({
    super.settings,
    required this.pageBuilder,
    this.transitionsBuilder = _defaultTransitionsBuilder,
    this.transitionDuration = const Duration(milliseconds: 300),
    this.reverseTransitionDuration = const Duration(milliseconds: 300),
    this.opaque = true,
    this.barrierDismissible = false,
    this.barrierColor,
    this.barrierLabel,
    this.maintainState = true,
    super.fullscreenDialog,
  })

PageRouteBuilder也是PageRoute的一种,在构建PageRouteBuilder的时候,通过管制不同的属性值,咱们能够自在管制pageBuilder,transitionsBuilder,transitionDuration,reverseTransitionDuration等个性。

能够看到自在水平还是十分高的。

其中pageBuilder是路由将会跳转的页面,这个是必须要指定的,要不然路由也就没有意义了。

另外路由转换的成果能够经由transitionsBuilder来设置。

这里的RouteTransitionsBuilder是一个Function,返回一个Widget:

typedef RouteTransitionsBuilder = Widget Function(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child);

所以实践上,咱们能够返回任何widget,然而一般来说,咱们会返回一个AnimatedWidget,示意一个动画成果。

flutter动画根底

flutter中有个专门的动画包叫做flutter/animation.dart, flutter中所有动画的外围叫做Animation。

Animation中定义了很多listener用来监控动画的变动状况,并且还提供了一个AnimationStatus来存储以后的动画状态:

abstract class Animation<T> extends Listenable implements ValueListenable<T> {
  const Animation();

  AnimationWithParentMixin<T>

  @override
  void addListener(VoidCallback listener);

  @override
  void removeListener(VoidCallback listener);

  void addStatusListener(AnimationStatusListener listener);

  void removeStatusListener(AnimationStatusListener listener);

  AnimationStatus get status;

AnimationStatus是一个枚举类,它蕴含了当初动画的各种状态:

enum AnimationStatus {
  dismissed,

  forward,

  reverse,

  completed,
}

dismissed示意动画暂停在结尾。

forward示意动画在从头到尾播放。

reverse示意动画在从尾到头播放。

completed示意动画播放结束,停在了结尾。

有了动画的示意之后,如何对动画进行管制呢?这里就须要用到AnimationController了。

AnimationController能够管制动画的duration,动画的最低值lowerBound默认是0.0,动画的最高值upperBound默认是1.0等等。

默认状况AnimationController中从最低值到最高值是线性变动的,如果你想设置不同的Bound值,那么能够尝试自定义 Animatable, 如果你想动画的变动是非线性的,那么能够尝试继承Animation来实现本人的变动曲线。

实现一个自定义的route

这里咱们应用flutter中的SlideTransition,SlideTransition是一个AnimatedWidget,它示意的是一个组件的地位变动的动画。

class SlideTransition extends AnimatedWidget {
  const SlideTransition({
    super.key,
    required Animation<Offset> position,
    this.transformHitTests = true,
    this.textDirection,
    this.child,
  }) : assert(position != null),
       super(listenable: position);

看下它的构造函数,能够看到SlideTransition须要一个position的属性,这个position是一个Animation对象,外面蕴含的是Offset。

同时这个position是一个listenable对象,通过监听外面Offset的变动,从而从新build对应的widget从而实现动画的成果。

Offset是一个示意地位的类,(0,0) 示意这个widget的左顶点在屏幕的左上角,同样的(1,1)示意这个widget的左顶点在屏幕的右下角。

因为route过后是一个新的页面,咱们心愿呈现一个页面从右下角挪动到左上角的动画,那么咱们能够这样做:

Route customRoute() {
  return PageRouteBuilder(
    pageBuilder: (context, animation, secondaryAnimation) => const SecondPage(),
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      const begin = Offset(1.0, 1.0);
      const end = Offset.zero;
      const curve = Curves.easeOut;

      var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));

      return SlideTransition(
        position: animation.drive(tween),
        child: child,
      );
    },
  );
}

这里的begin和end示意widget从屏幕的右下角挪动到了屏幕的左上角。

Tween示意的是开始值和完结值之间的线性插值,是一个动静过程,另外咱们还能够这个插值变动的曲线,这里应用了CurveTween,选中了Curves.easeOut这种曲线类型。

最初调用animation.drive办法把Tween和Animation关联起来,这样一个路由动画就实现了。

总结

最初程序运行的后果如下:

其实flutter中的动画很简略,大家记住就是widget地位沿不同的曲线变动即可。

本文的例子:https://github.com/ddean2009/learn-flutter.git

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理