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

科技资讯 投稿 5700 0 评论

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

目录
    简介
  • 自定义跳转使用
  • flutter动画基础
  • 实现一个自定义的route
  • 总结

简介

但是MaterialPageRoute太普通了,如果我们想要做点不同的跳转特效应该如何处理呢?

自定义跳转使用

正常情况下,我们进行路由跳转需要用到Navigator和MaterialPageRoute,如下所示:

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

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

先来看下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是路由将会跳转的页面,这个是必须要指定的,要不然路由也就没有意义了。

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

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

所以理论上,我们可以返回任何widget,但是一般来说,我们会返回一个AnimatedWidget,表示一个动画效果。

flutter动画基础

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表示动画暂停在开头。

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

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

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

实现一个自定义的route

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。

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

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从屏幕的右下角移动到了屏幕的左上角。

最后调用animation.drive方法把Tween和Animation关联起来,这样一个路由动画就完成了。

总结

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

编程笔记 » flutter系列之:如何自定义动画路由

赞同 (28) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽