当前位置: 首页 > news >正文

flutter 页面加载动画_为页面切换加入动画效果

在不同路由(或界面)之间进行切换的时候,许多设计语言,例如 Material 设计,都定义了一些标准行为。但有时自定义路由会让 app 看上去更加的独特。为了更好的完成这一点,PageRouteBuilder 提供了一个 Animation 对象。这个 Animation 能够通过结合

Tween 以及 Curve 对象来自定义路由转换动画。这篇指南将会展示如何在两个路由之间切换时使用从屏幕底部动画出来的路由。

A design language, such as Material, defines standard behaviors when

transitioning between routes (or screens). Sometimes, though, a custom

transition between screens can make an app more unique. To help,

PageRouteBuilder provides an Animation object.

This Animation can be used with Tween and

Curve objects to customize the transition animation.

This recipe shows how to transition between

routes by animating the new route into view from

the bottom of the screen.

要创建这个自定义路由动画,这篇指南使用了以下步骤:

To create a custom page route transition, this recipe uses the following steps:

搭建一个 PageRouteBuilder

Set up a PageRouteBuilder

创建一个 Tween

Create a Tween

添加一个 AnimatedWidget

Add an AnimatedWidget

使用 CurveTween

Use a CurveTween

组合这两个 Tween

Combine the two Tweens

1. 搭建一个 PageRouteBuilder

1. Set up a PageRouteBuilder

我们从使用一个 PageRouteBuilder 来创建一个 Route。

PageRouteBuilder 有两个回调,第一个是创建这个路由的内容(pageBuilder),另一个则是创建一个路由的转换器(transitionsBuilder)。

To start, use a PageRouteBuilder to create a Route.

PageRouteBuilder has two callbacks, one to build the content of the route

(pageBuilder), and one to build the route’s transition (transitionsBuilder).

备忘

transitionsBuilder 的 child 参数是通过 pageBuilder 方法来返回一个 transitionsBuilder widget,这个 pageBuilder 方法仅会在第一次构建路由的时候被调用。框架能够自动避免做额外的工作,因为整个过渡期间 child 保存了同一个实例。

The child parameter in transitionsBuilder is the widget returned from

pageBuilder. The pageBuilder function is only called the first time the

route is built. The framework can avoid extra work because child stays the

same throughout the transition.

下面的样例将会创建两个路由:一个主页路由,包含了 “Go!” 按钮,还有第二个路由,包含了一个显示 “Page 2 的标题。

The following example creates two routes: a home route with a “Go!” button, and

a second route titled “Page 2”.

import 'package:flutter/material.dart';

main() {

runApp(MaterialApp(

home: Page1(),

));

}

class Page1 extends StatelessWidget {

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(),

body: Center(

child: ElevatedButton(

child: Text('Go!'),

onPressed: () {

Navigator.of(context).push(_createRoute());

},

),

),

);

}

}

Route _createRoute() {

return PageRouteBuilder(

pageBuilder: (context, animation, secondaryAnimation) => Page2(),

transitionsBuilder: (context, animation, secondaryAnimation, child) {

return child;

},

);

}

class Page2 extends StatelessWidget {

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(),

body: Center(

child: Text('Page 2'),

),

);

}

}

2. 创建一个 Tween

2. Create a Tween

为了使新页面从底部动画出来,它应该从 Offset(0,1) 到 Offset(0, 0) 进行动画。(通常我们会使用 Offset.zero 构造器。)在这个情况下,对于 ‘FractionalTranslation’ widget 来说偏移量是一个 2D 矢量值。将 dy 参数设为 1,这代表在竖直方向上切换整个页面的高度。

To make the new page animate in from the bottom, it should animate from

Offset(0,1) to Offset(0, 0) (usually defined using the Offset.zero

constructor). In this case, the Offset is a 2D vector for the

‘FractionalTranslation’ widget.

Setting the dy argument to 1 represents a vertical translation one

full height of the page.

transitionsBuilder 的回调有一个 animation 参数。它其实是一个 Animation,提供 0 到 1 的值。使用 Tween 来将 Animation转为 Animation。

The transitionsBuilder callback has an animation parameter. It’s an

Animation that produces values between 0 and 1. Convert the

Animationinto an Animationusing a Tween:

transitionsBuilder: (context, animation, secondaryAnimation, child) {

var begin = Offset(0.0, 1.0);

var end = Offset.zero;

var tween = Tween(begin: begin, end: end);

var offsetAnimation = animation.drive(tween);

return child;

},

3. 使用 AnimatedWidget

3. Use an AnimatedWidget

Flutter 有一堆继承自 AnimatedWidget 的 widget,它们能够在动画的值发生改变时自动重建自己。举个例子,SlideTransition 拿到一个 Animation

并在动画改变时使用 FractionalTranslation widget 转换其子级。

Flutter has a set of widgets extending AnimatedWidget

that rebuild themselves when the value of the animation changes. For instance,

SlideTransition takes an Animation and translates its child (using a

FractionalTranslation widget) whenever the value of the animation changes.

AnimatedWidget 返回了一个带有 Animation

的 SlideTransition,以及 child widget:

AnimatedWidget Return a SlideTransition

with the Animation and the child widget:

transitionsBuilder: (context, animation, secondaryAnimation, child) {

var begin = Offset(0.0, 1.0);

var end = Offset.zero;

var tween = Tween(begin: begin, end: end);

var offsetAnimation = animation.drive(tween);

return SlideTransition(

position: offsetAnimation,

child: child,

);

},

4. 使用 CurveTween

4. Use a CurveTween

Flutter 提供了一系列缓和曲线,可以调整一段时间内的动画速率。

Curves 类提供了一个提前定义的用法相似的 curves。例如,Curves.easeOut 将会让动画开始很快结束很慢。

Flutter provides a selection of easing curves that

adjust the rate of the animation over time.

The Curves class

provides a predefined set of commonly used curves.

For example, Curves.easeOut

makes the animation start quickly and end slowly.

要使用 Curve,创建一个 CurveTween 并传一个 Curve:

To use a Curve, create a new CurveTween

and pass it a Curve:

var curve = Curves.ease;

var curveTween = CurveTween(curve: curve);

新的 Tween 依然提供 0 到 1 之间的值。在下一步中,它将会结合第二步中提到的 Tween。

This new Tween still produces values from 0 to 1. In the next step, it will be

combined the Tween from step 2.

5. 结合两个 Tween

5. Combine the two Tweens

为了结合两个 tween,请使用 chain():

To combine the tweens,

use chain():

var begin = Offset(0.0, 1.0);

var end = Offset.zero;

var curve = Curves.ease;

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

它们通过把这个 tween 传递给 animation.drive()

来创建一个新的 Animation,然后你就能把它传给 SlideTransition widget:

Then use this tween by passing it to animation.drive(). This creates a new

Animation that can be given to the SlideTransition widget:

return SlideTransition(

position: animation.drive(tween),

child: child,

);

这个新的 Tween(或者是能够动画的东西)通过评估 CurveTween 来提供 Offset,然后评估 Tween。当动画运行时,值都被这条命令计算出:

This new Tween (or Animatable) produces Offset values by first evaluating the

CurveTween, then evaluating the Tween. When the animation runs, the

values are computed in this order:

这个动画提供了从 0 到 1 的值。(通过 transitionsBuilder 的值提供)

The animation (provided to the transitionsBuilder callback) produces values

from 0 to 1.

这个 CurveTween 根据其将这些值映射到介于 0 和 1 之间的新曲线值。

The CurveTween maps those values to new values between 0 and 1 based on its

curve.

Tween 将 double 值映射为 Offset 值。

The Tween maps the double values to Offset values.

使用缓动曲线创建 Animation 的另一种方法是使用 CurvedAnimation:

Another way to create an Animation with an easing curve is to use a

CurvedAnimation:

transitionsBuilder: (context, animation, secondaryAnimation, child) {

var begin = Offset(0.0, 1.0);

var end = Offset.zero;

var curve = Curves.ease;

var tween = Tween(begin: begin, end: end);

var curvedAnimation = CurvedAnimation(

parent: animation,

curve: curve,

);

return SlideTransition(

position: tween.animate(curvedAnimation),

child: child,

);

}

交互式样例

Interactive example

import 'package:flutter/material.dart';

main() {

runApp(MaterialApp(

home: Page1(),

));

}

class Page1 extends StatelessWidget {

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(),

body: Center(

child: ElevatedButton(

child: Text('Go!'),

onPressed: () {

Navigator.of(context).push(_createRoute());

},

),

),

);

}

}

Route _createRoute() {

return PageRouteBuilder(

pageBuilder: (context, animation, secondaryAnimation) => Page2(),

transitionsBuilder: (context, animation, secondaryAnimation, child) {

var begin = Offset(0.0, 1.0);

var end = Offset.zero;

var curve = Curves.ease;

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

return SlideTransition(

position: animation.drive(tween),

child: child,

);

},

);

}

class Page2 extends StatelessWidget {

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(),

body: Center(

child: Text('Page 2'),

),

);

}

}

相关文章:

  • 可变悬挂与空气悬挂的区别_可调悬挂和空气悬挂有什么区别啊,求解释
  • base64图裁剪 php_php解析base64数据生成图片的方法
  • cahrt框架 ios_iOS使用Charts框架绘制柱形图
  • 关于python搞笑段子精选_你能讲一个让人瞬间爆笑的笑话吗?
  • php yield 个人小解_php 新特性之yield大数组处理优化
  • div盒子边距_CSS | 盒子模型之外边距(margin)
  • php mongodb 按照日期统计_PHP程序员应该掌握哪些技术?
  • 图片在section上下居中_停!你的时间不应该花在无谓的图片/文字对齐上
  • python小课堂28_python课堂整理28----re模块
  • fabric shim安装合约_Fabric 2.0 实战 - 设置背书策略
  • springboot 单测加入参数_SpringBoot加Lambda进行参数校验的一个通用方案
  • java 炸金花_炸金花绝对大小计算 比较及排序算法(Java)
  • ios请求头解决参数中文乱码_vue Axios 向后端提交参数 请求头 json 方式(Content-Type: application/json; charset=UTF-8)...
  • three相机在模型上_javascript – Three.js围绕物体旋转相机(可能会移动)
  • ominipeek 发包_WildPackets的著名的抓包软件Omnipeek
  • [LeetCode] Wiggle Sort
  • DataBase in Android
  • learning koa2.x
  • MySQL Access denied for user 'root'@'localhost' 解决方法
  • Rancher如何对接Ceph-RBD块存储
  • webpack项目中使用grunt监听文件变动自动打包编译
  • Windows Containers 大冒险: 容器网络
  • 前嗅ForeSpider中数据浏览界面介绍
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 算法系列——算法入门之递归分而治之思想的实现
  • 用mpvue开发微信小程序
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • ​configparser --- 配置文件解析器​
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • #etcd#安装时出错
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (13)Hive调优——动态分区导致的小文件问题
  • (Forward) Music Player: From UI Proposal to Code
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (Matlab)基于蝙蝠算法实现电力系统经济调度
  • (二)WCF的Binding模型
  • (二)正点原子I.MX6ULL u-boot移植
  • (分布式缓存)Redis分片集群
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (转载)Google Chrome调试JS
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET/C# 的字符串暂存池
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • /*在DataTable中更新、删除数据*/
  • [ C++ ] template 模板进阶 (特化,分离编译)
  • [ 攻防演练演示篇 ] 利用通达OA 文件上传漏洞上传webshell获取主机权限
  • [20171101]rman to destination.txt
  • [20180312]进程管理其中的SQL Server进程占用内存远远大于SQL server内部统计出来的内存...
  • [C#]winform制作圆形进度条好用的圆环圆形进度条控件和使用方法
  • [CVPR2021]Birds of a Feather: Capturing Avian Shape Models from Images
  • [E单调栈] lc2487. 从链表中移除节点(单调栈+递归+反转链表+多思路)
  • [HNOI2008]水平可见直线