Code前端首页关于Code前端联系我们

Flutter开发指南:如何同步动画路径?

terry 2年前 (2023-09-22) 阅读数 82 #移动小程序

简介

flutter中有一个自定义的Route组件,叫做MaterialPageRoute。正常情况下,如果我们跳转到flutter,需要将MaterialPageRoute发送给Navigator。

但是MaterialPageRoute太常见了。如果我们想再做一次跳跃结果怎么办?

让我们看看。

使用自定义跳转

一般情况下,我们需要使用Navigator和MaterialPageRoute进行路线跳转,如下图:

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

如果要应用自定义动画,需要修复道路。

在flutter中,需要使用PageRouteBuilder来构建路由。

我们先看一下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是一个返回Widget的Function:

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

所以理论上我们可以返回任何Widget,但一般情况下我们会返回一个AnimatedWidget,它代表动画效果。

flutter动画的基本方法

有一个flutter专用的动画包,名为flutter/animation.dart。 flutter 中所有动画的基础称为动画。

Animation 定义了多个监听器来跟踪动画的变化,同时还提供了一个 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 是一个枚举类,包含了各种动画状态。now:

enum AnimationStatus {
  dismissed,

  forward,

  reverse,

  completed,
}

表示动画正在执行一开始就停顿了。

前进表示从头到尾播放动画。

反向表示动画从结尾播放到开头。

finished 表示游戏结束,动画到最后停止。

拿到动画后,如何控制动画呢?这里需要AnimationController。

AnimationController 可以控制动画时长。动画的下限值 lowerBound 变为 0.0,动画的上限值 upperBound 变为 1.0,依此类推。如果你想设置不同的Bound值,你可以尝试配置Animatable。如果你希望动画过渡是非线性的,可以尝试继承Animation。应用您自己的调整曲线。

应用自定义路径

这个在 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属性。这个位置是一个Animation对象,它包含一个Offset。

那时候,这个地方是值得听的。通过控制Offset的变化,可以调整相应的widget来得到动画效果。

Offset 是表示位置的类。 (0,0) 表示该小部件的左顶点位于屏幕的左上角。同样,(1,1) 表示该小部件的左顶点位于屏幕的右下角。

由于路径后面有一个新页面,我们想要一个将页面从右下角移动到左上角的动画,我们可以这样做:

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,
      );
    },
  );
}

这里的开始和结束表示小部件已从屏幕右下角移动到屏幕左上角。

Tween 表示起始值和结束值之间的线性过渡,这是一个动态过程。此外,还可以对变化曲线进行插值。这里使用了CurveTween,并且选择了Curves.easeOut曲线类型。

最后调用animation.drive方法将Tween连接到Animation上,这样动画就完成了。

总结

程序运行最终结果如下:flutter开发教程:如何自定义动画路由?

其实flutter动画很简单。请记住,小部件位置在不同的曲线上会发生变化。

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

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门