首页 > 其他分享 >Flutter 页面专场动画

Flutter 页面专场动画

时间:2023-12-26 14:57:55浏览次数:39  
标签:动画 begin const Offset Tween child end Flutter 页面

在不同路由(或界面)之间进行切换的时候,许多设计语言,例如 Material 设计,都定义了一些标准行为。但有时自定义路由会让 app 看上去更加的独特。为了更好的完成这一点,PageRouteBuilder 提供了一个 Animation 对象。这个 Animation 能够通过结合 Tween 以及 Curve 对象来自定义路由转换动画。这篇指南将会展示如何在两个路由之间切换时使用从屏幕底部动画出来的路由。

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

  1. 搭建一个 PageRouteBuilder

  2. 创建一个 Tween

  3. 添加一个 AnimatedWidget

  4. 使用 CurveTween

  5. 组合这两个 Tween

一、搭建一个 PageRouteBuilder

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

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

import 'package:flutter/material.dart';

import '../components/photo_hero.dart';
import 'hero_photo.dart';

class HeroPage extends StatelessWidget {
  const HeroPage({super.key});
  static const url =
      'images/products/O1CN01yvMCj11GkmaVukfRK_!!2652950661.jpg_Q75.jpg';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('HeroPage'),
      ),
      body: Center(
        child: PhotoHero(
          width: 60,
          height: 60,
          imageUrl: url,
          onTap: () {
            // Navigator.pushNamed(context, '/herophoto', arguments: url);
            Navigator.of(context).push(_createRoute(url));
          },
        ),
      ),
    );
  }
}

Route _createRoute(String url) {
  return PageRouteBuilder(
    pageBuilder: (context, animation, secondaryAnimation) =>
        HeroPhoto(url: url),
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      return child;
    },
  );
}

二、创建一个Tween

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

transitionsBuilder: (context, animation, secondaryAnimation, child) {
  const begin = Offset(0.0, 1.0);
  const end = Offset.zero;
  final tween = Tween(begin: begin, end: end);
  final offsetAnimation = animation.drive(tween);
  return child;
},

三、使用 AnimatedWidget

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

AnimatedWidget 返回了一个带有 AnimationSlideTransition,以及 child widget:

transitionsBuilder: (context, animation, secondaryAnimation, child) {
  const begin = Offset(0.0, 1.0);
  const end = Offset.zero;
  final tween = Tween(begin: begin, end: end);
  final offsetAnimation = animation.drive(tween);

  return SlideTransition(
    position: offsetAnimation,
    child: child,
  );
},

四、使用 CurveTween

Flutter 提供了一系列缓和曲线,可以调整一段时间内的动画速率。 Curves 类提供了一个提前定义的用法相似的 curves。例如,Curves.easeOut 将会让动画开始很快结束很慢。

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

var curve = Curves.ease;
var curveTween = CurveTween(curve: curve);

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

五、结合两个 Tween

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

const begin = Offset(0.0, 1.0);
const end = Offset.zero;
const curve = Curves.ease;

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

它们通过把这个 tween 传递给 animation.drive() 来创建一个新的 Animation,然后你就能把它传给 SlideTransition widget:

return SlideTransition(
  position: animation.drive(tween),
  child: child,
);
这个新的 Tween(或者是能够动画的东西)通过评估 CurveTween 来提供 Offset,然后评估 Tween<Offset>。当动画运行时,值都被这条命令计算出:

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

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

3. Tween<Offset> 将 double 值映射为 Offset 值。

使用缓动曲线创建 Animation<Offset> 的另一种方法是使用 CurvedAnimation:
```dart
transitionsBuilder: (context, animation, secondaryAnimation, child) {
  const begin = Offset(0.0, 1.0);
  const end = Offset.zero;
  const curve = Curves.ease;

  final tween = Tween(begin: begin, end: end);
  final curvedAnimation = CurvedAnimation(
    parent: animation,
    curve: curve,
  );

  return SlideTransition(
    position: tween.animate(curvedAnimation),
    child: child,
  );
}

标签:动画,begin,const,Offset,Tween,child,end,Flutter,页面
From: https://www.cnblogs.com/angelwgh/p/17928105.html

相关文章

  • 使用代码生成工具快速开发应用-结合后端Web API提供接口和前端页面快速生成,实现通用的
    在前面随笔《在Winform应用中增加通用的业务编码规则生成》,我介绍了基于Winform和WPF的一个通用的业务编码规则的管理功能,本篇随笔介绍基于后端WebAPI接口,实现快速的Vue3+ElementPlus前端界面的开发整合,同样是基于代码生成工具实现快速的前端代码的生成处理。1、通用的业务编码规......
  • Flutter hero动画
    在Flutter中,图像从当前页面转到另一个页面称为hero动画,相同的动作有时也被称为共享元素过渡。hero动画基本结构在不同页面分别使用两个herowidgets,同时使用配对的标签来实现动画Navigator管理含有app页面的堆栈。推送一个页面或弹出一个Navigator堆栈中的页面会......
  • 使用 Flutter 制作地图应用
    使用Flutter制作地图应用本文主要介绍使用Flutter制作地图应用在本文中,我将向您展示如何使用Flutter向您的应用程序添加映射功能。对于本教程,您将不需要googlemapsAPI,因此您无需支付任何费用,因为我们将使用另一个免费API,所以不用多说,让我们深入研究它。依赖关系创建一个......
  • 十九、显示动画-位置改变
    ArkUI中,产生动画的方式是改变属性值且指定动画参数。动画参数包含了如动画的时长、变化规律(即曲线)等参数,当属性值发生变化后,按照动画参数,从原来的状态过渡到新的状态,即形成一个动画。AnimateParam对象说明名称类型描述durationnumber动画持续时间,单位为毫秒。默认值......
  • lottie 动画在 vue 中的使用
    前言最近我所负责的项目中,我采用了动画效果,并开始使用gif来实现。然而,在实践过程中,我发现gif格式的动画在git中出现了明显的锯齿感,这让我非常困扰。为了追求更完美的表现效果,我最终选择了lottie来实现我的动画需求。我深知动画效果的呈现对于用户体验至关重要,因此我非常......
  • 某居客页面爬虫
    支持2023版本,每过一段时间会有验证码验证,脚本会提醒手动输入,爬虫本身不会进行验证码处理(可自行扩展)。pip前置安装项:pipinstalllogzeropipinstallbs4pipinstallrequestspipinstallhtml5libpipinstalllxml代码:#!/usr/bin/envpython#-*-coding:utf-8-*-im......
  • Salesforce LWC学习(四十七) 标准页面更新以后自定义页面如何捕捉?
    本篇参考: https://developer.salesforce.com/docs/atlas.en-us.platform_events.meta/platform_events/platform_events_subscribe_lc.htmhttps://developer.salesforce.com/docs/component-library/bundle/lightning-emp-api/documentationsalesforce零基础学习(九十六)Platfor......
  • 微信页面公众号页面 安全键盘收起后键盘下方页面留白
      微信浏览器打开H5页面和公众号页面,输入密码时调起安全键盘,键盘收起后键盘下方页面留白解决办法: 1、(简单)只有在调起安全键盘(输入密码)的时候会出现这种情况,将input属性改为number,添加一个加密样式就可以了<inputtype="npmber"name="password"placeholder="请输入......
  • 跨页面新手引导 思路
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=......
  • 27、flutter Dialog 弹窗
    AlertDialog//放在State<>之下void_alertDialog()async{varresult=awaitshowDialog(barrierDismissible:true,//表示点击灰色背景的时候是否消失弹出框context:context,builder:(context){returnAlertDialog(......