Flutter 用自定义转场动画实现页面切换

fluro 转场动画源码 在使用自定义转场动画前,先扒一扒 fluro 的源码,通过源码可以发现这么一个标准的转场方法:

RouteTransitionsBuilder _standardTransitionsBuilder(
      TransitionType? transitionType) {
    return (BuildContext context, Animation<double> animation,
        Animation<double> secondaryAnimation, Widget child) {
      if (transitionType == TransitionType.fadeIn) {
        return FadeTransition(opacity: animation, child: child);
      } else {
        const Offset topLeft = const Offset(0.0, 0.0);
        const Offset topRight = const Offset(1.0, 0.0);
        const Offset bottomLeft = const Offset(0.0, 1.0);

        Offset startOffset = bottomLeft;
        Offset endOffset = topLeft;
        if (transitionType == TransitionType.inFromLeft) {
          startOffset = const Offset(-1.0, 0.0);
          endOffset = topLeft;
        } else if (transitionType == TransitionType.inFromRight) {
          startOffset = topRight;
          endOffset = topLeft;
        } else if (transitionType == TransitionType.inFromBottom) {
          startOffset = bottomLeft;
          endOffset = topLeft;
        } else if (transitionType == TransitionType.inFromTop) {
          startOffset = Offset(0.0, -1.0);
          endOffset = topLeft;
        }

        return SlideTransition(
          position: Tween<Offset>(
            begin: startOffset,
            end: endOffset,
          ).animate(animation),
          child: child,
        );
      }
    };
  }

从源码可以看出,根据不同枚举返回了不同的动画(即 transitionBuilder),其中TransitionType.fadeIn使用的是Flutter 自带的 FadeTransition,通过改变透明度来完成动画。而其他的左滑入、右滑入、下滑入和上滑入都是从初始偏移位置滑动到结束位置,使用的是 SlideTransition。Flutter 除了上述的 FadeTransition、SlideTransition 之外,还有如下的常用转场形式:

  • RotationTransition:旋转转场
  • ScaleTransition:缩放转场

既然是这样,我们可以依葫芦画瓢,先用系统其他的转场效果做一个自定义的转场看看。

旋转转场动画

先来看看旋转的转场RotationTransition,RotationTransition 的构造方法定义如下:

const RotationTransition({
    Key? key,
    required Animation<double> turns,
    this.alignment = Alignment.center,
    this.child,
  })  : assert(turns != null),
        super(key: key, listenable: turns);

其中 turns 是动画控制,表示旋转的弧度数,等于动画控制值乘以2π。alignment 表示旋转围绕的中心位置,默认是居中的。旋转的弧度不要太大,否则动画过快,导致不太好看,经过验证,推荐的起始值0.2至0.3之间,结束值为0表示回到正常位置。起始值如果为负,则是顺时针;如果为正则是逆时针,示例代码如下:

//逆时针围绕中心旋转
RouterManager.router.navigateTo(
  context,
  RouterManager.transitionPath,
  transition: TransitionType.custom,
  transitionBuilder:
      (context, animation, secondaryAnimation, child) {
    return RotationTransition(
      turns: Tween<double>(
        begin: 0.25,
        end: 0.0,
      ).animate(animation),
      child: child,
    );
  },
);

//...
//顺时针围绕左下角旋转
RouterManager.router.navigateTo(
  context,
  RouterManager.transitionPath,
  transition: TransitionType.custom,
  transitionBuilder:
      (context, animation, secondaryAnimation, child) {
    return RotationTransition(
      alignment: Alignment.bottomLeft,
      turns: Tween<double>(
        begin: -0.25,
        end: 0.0,
      ).animate(animation),
      child: child,
    );
  },
);

其中 Tween 是系统自带的线性插值方法。

缩放转场动画

缩放转场这类在图片预览会比较常见,一般是从较小的比例缩放到1:1比例。使用方式和旋转转场类似,示例代码如下:

RouterManager.router.navigateTo(
  context,
  RouterManager.transitionPath,
  transition: TransitionType.custom,
  transitionBuilder:
      (context, animation, secondaryAnimation, child) {
    return ScaleTransition(
      scale: Tween<double>(
        begin: 0.5,
        end: 1.0,
      ).animate(animation),
      child: child,
    );
  },
);

自定义转场动画

通过阅读源码,其实可以发现RotationTransition、ScaleTransition 都是继承自 AnimatedWidget,因此我们可以自己写一个自定义的 Transition 继承自 AnimatedWidget,在 build方法中返回一个 Transform 对象即可。通过这种方式可以做自定义的转场动画效果。我们以变形为例,可以利用 Matrix4的 skew 方法,在 x 和 y 轴进行变形,就可以得到转场类似卡片变形的效果。也可以只在 X 轴或 Y 轴变形(skewX和 skewY 方法)。这里以 x,y 轴同时变形定义了一个转场动画:

class SkewTransition extends AnimatedWidget {
  const SkewTransition({
    Key key,
    Animation<double> turns,
    this.alignment = Alignment.center,
    this.child,
  })  : assert(turns != null),
        super(key: key, listenable: turns);

  Animation<double> get turns => listenable as Animation<double>;

  final Alignment alignment;

  final Widget child;

  @override
  Widget build(BuildContext context) {
    final double turnsValue = turns.value;
    final Matrix4 transform =
        Matrix4.skew(turnsValue * pi * 2.0, turnsValue * pi * 2.0);
    return Transform(
      transform: transform,
      alignment: alignment,
      child: child,
    );
  }
}

使用方式和 RotationTransition 类似:

RouterManager.router.navigateTo(
  context,
  RouterManager.transitionPath,
  transition: TransitionType.custom,
  transitionBuilder:
      (context, animation, secondaryAnimation, child) {
    return SkewTransition(
      turns: Tween<double>(
        begin: -0.05,
        end: 0.0,
      ).animate(animation),
      child: child,
    );
  },
);

实际也可以尝试使用围绕 X 轴旋转,围绕 Y 轴旋转,以及变更中心点位置(alignment)来实现不同的动画转场效果。如果需要更为复杂的动画效果,则可以研究动画的实现,后续篇章将有对应动画的介绍。

运行效果

运行效果如下图所示:

以上就是Flutter 用自定义转场动画实现页面切换的详细内容,更多关于Flutter 自定义转场动画的资料请关注我们其它相关文章!

(0)

相关推荐

  • Flutter 生成图片保存至相册的示例

    目录 基本思路 添加依赖 实现代码 遇到一个需求,需要用 Flutter 生成图片,最终实现的效果如下: 基本思路 使用 Canvas 绘制图片中各元素,然后使用 PictureRecorder 进行记录生成. 添加依赖 qr_flutter: ^3.1.0 image_gallery_saver: ^1.2.2 fluttertoast: ^4.0.0 实现代码 import 'dart:ui' as ui; import 'dart:ui'; import 'package:flutter/

  • Flutter 使用fluro的转场动画进行页面切换

    在 fluro 中,定义路由处理器 Handler 时可以指定该页面的默认转场形式,或者在使用 navigateTo 方法是可以设置页面跳转transition参数来设定个性化的转场形式.本篇演示了fluro 内置的转场动画,效果如下图所示. 转场形式 fluro 的转场形式通过 TransitionType枚举定义,如下所示: enum TransitionType { native, //原生形式,和原生的保持一致,默认 nativeModal, //原生模态跳转 inFromLeft, /

  • Flutter 底部弹窗如何实现多项选择

    多选和单选的不同之处 单选的时候,选中一个就可以直接把结果返回,因此本身底部弹窗无需状态管理.但到多选的时候,需要知道当前选中的选项,有选项被点击的时候需要存储下来,当再次被点击的时候要清空这个选项,同时界面还需要同步更新,因此就涉及到状态管理了. 实现方式 在Flutter 中提供了一个 StatefulBuilder 的类,提供了一个 builder方法构建有状态组件,并且提供了状态更新方法,因此在里面完成状态管理. StatefulBuilder(builder: (context1, s

  • Flutter 利用CustomScrollView实现滑动效果

    我们在之前的文章中//www.jb51.net/article/213709.htm 使用了 ListView 将几个 GridView 组合在一起实现滑动效果,今天利用CustomScrollView改造一下代码 CustomScrollView 简介 CustomScrollView的常用属性如下: slivers:最重要的属性,由多个SliverXX组件组成的数组,包括如 SliverList(对应 ListView),SliverGrid(对应 GridView)等,如果普通组件无法直接

  • Flutter如何完成路由拦截,实现权限管理

    之前几篇介绍了 fluro 的路由管理和转场动画,本篇介绍如何完成路由拦截,进而实现权限管理."此路是我开,此树是我栽.若是没权限,403到来!" 相关文章 若想了解 flutter 的路由相关篇章,请查阅下面的篇章: //www.jb51.net/article/215167.htm //www.jb51.net/article/214856.htm //www.jb51.net/article/215564.htm //www.jb51.net/article/215549.htm

  • Flutter开发中的路由参数处理

    目录 Navigator 的 push 和 pop方法 Navigator 导航器的 push 和 pop 方法可以携带参数在页面间传递,其他变形的方法也一样.pushNamed 方法原型如下: Future<T?> pushNamed<T extends Object?>( String routeName, { Object? arguments, }) { return push<T>(_routeNamed<T>(routeName, argumen

  • Flutter app页面路由以及路由拦截的实现

    为什么要使用路由 在之前我们的代码中,页面跳转使用的代码如下所示: Navigator.of(context).push( MaterialPageRoute(builder: (context) => LoginPage()), ); 在开发过程中,随着页面的增加,如果继续使用这种方式会有如下缺陷: 代码耦合严重:涉及到页面跳转的地方就需要插入页面的构造函数,意味着需要知道其他页面的构建方式. 不易维护:一旦某个页面发生了变化,需要将涉及到该页面的跳转全部改变. 权限控制不方便:假设某些页面需

  • 如何在Flutter中嵌套Android布局

    效果 本文具体demo效果如下 开发 1.首先创建flutter项目,在项目中定义好flutter需要展示布局: @override Widget build(BuildContext context) { return Scaffold( body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Expanded( child: Center( child: Text( 'Android按钮

  • Flutter 路由插件fluro的使用

    前面两篇文章我们介绍了Flutter 的原生导航器 Navigator 实现页面跳转,路由及路由拦截的使用,具体可以参考之前的文章: //www.jb51.net/article/215167.htm //www.jb51.net/article/214856.htm 使用原生的路由基本上能够满足大部分需求,但如果想要对页面做类似浏览器 url 那样的路由,或者控制页面跳转的转场动画,那么原生的路由需要做不少的改造.在 pub 上,有优秀的路由插件 fluro 解决这类问题. fluro的使用方

  • Flutter 底部弹窗ModelBottomSheet的使用示例

    实现效果 最终实现效果如图片所示,分布演示了基础的,全屏的和自定义的底部弹窗形式. 代码结构 在消息页面 message.dart 中,使用 Column 组件构建了三个按钮,点击每个按钮调用不同的底部弹窗显示.这部分代码不展示,核心注意的方式是按钮的 onPressed 响应方法,需要使用 async 修饰,这是因为 ModalBottomSheet 的返回结果是一个 Future 对象,需要通过 await 来获取返回结果. onPressed: () async { int selecte

随机推荐