Flutter可执行屏幕动画的AnimateView

news/2024/10/23 9:29:59/

1.让动画使用起来就像使用widget。

2.可自定义动画。

3.内置平移动画。

演示:

 代码:

import 'dart:math';
import 'package:flutter/cupertino.dart';class AnimateView extends StatefulWidget {///子Widgetfinal Widget child;///动画自定义final IAnimate? animate;///是否需要每次刷新时都执行动画final bool isNeedFlashEveryTime;const AnimateView({super.key,required this.child,this.animate,this.isNeedFlashEveryTime = false,});@overrideState<StatefulWidget> createState() => _AnimateViewState();
}class _AnimateViewState extends State<AnimateView>with TickerProviderStateMixin {late IAnimate animate;late AnimationController controller;late Animation animation;@overridevoid initState() {super.initState();animate = widget.animate ??TranslationAnimate(angle: TranslationAnimateDirection.rightToLeft.angle);animate.init();controller = animate.getAnimationController(this);animation = animate.getAnimation(controller, this);//启动动画(正向执行)controller.forward();}@overridevoid didUpdateWidget(covariant AnimateView oldWidget) {super.didUpdateWidget(oldWidget);if (widget.isNeedFlashEveryTime) {animate = widget.animate ??TranslationAnimate(angle: TranslationAnimateDirection.rightToLeft.angle);animate.init();controller = animate.getAnimationController(this);animation = animate.getAnimation(controller, this);//启动动画(正向执行)controller.forward();}}@overrideWidget build(BuildContext context) {return animate.animate(context, widget.child, animation, controller);}
}///动画抽象类。
///实现该类,定制自己的动画。
abstract class IAnimate {///初始化void init();///获取AnimationControllerAnimationController getAnimationController(TickerProvider provider);///获取AnimationAnimation getAnimation(AnimationController controller, State<StatefulWidget> state);///定制自己的动画,每一个item都会调用到animate,///[widget] 执行动画之后的widget///[index] 列表的item的indexWidget animate(BuildContext context,Widget widget,Animation animation,AnimationController controller,);
}///平移动画
class TranslationAnimate extends IAnimate {///动画执行的总长度static double gap = 1000.0;///动画执行角度final int angle;///动画执行时长,毫秒(ms)final int duration;///进入动画还是出去动画final TranslationAnimateType type;///界面的宽,动画需要根据你需要操作的界面宽进行计算,不传代表屏幕宽final double? width;///界面的高,动画需要根据你需要操作的界面高进行计算,不传代表屏幕高final double? height;TranslationAnimate({this.angle = 0,this.duration = 500,this.type = TranslationAnimateType.translateIn,this.width,this.height,});@overrideWidget animate(BuildContext context, Widget widget, Animation animation,AnimationController controller) {final size = MediaQuery.of(context).size;double width = this.width ?? size.width;double height = this.height ?? size.height;double left = 0;double top = 0;///范围0.0->1000.0double animateValue = animation.value;int positiveAngle = angle;if (angle < 0) {int tempAngle = angle % 360;positiveAngle = 360 - tempAngle;}positiveAngle = positiveAngle % 360;///范围0->1double rate = animateValue / gap;if (type == TranslationAnimateType.translateIn) {rate = rate - 1;}if (positiveAngle >= 0 && positiveAngle <= 45 ||positiveAngle >= 135 && positiveAngle <= 225 ||positiveAngle > 315 && positiveAngle <= 360) {///移出距离以宽度为准left = rate * width;if (positiveAngle > 90 && positiveAngle < 270) {left = -left;}double tanValue = tan(positiveAngle * pi / 180);top = rate * width * tanValue;} else if (positiveAngle == 90) {top = rate * height;left = 0;} else if (positiveAngle == 270) {top = -rate * height;left = 0;} else {///移出距离以高度为准top = rate * height;if (positiveAngle > 180 && positiveAngle < 360) {top = -top;}double tanValue = tan(positiveAngle * pi / 180);if (tanValue == 0) {left = 0;} else {left = rate * height / tanValue;}}//print("angle=$positiveAngle");//print("left=$left");//print("top=$top");return Container(transform: Matrix4.translationValues(left, top, 0),child: widget,);}@overrideAnimation getAnimation(AnimationController controller, State<StatefulWidget> state) {return Tween(begin: 0.0, end: gap).animate(controller)..addListener(() {if (state.mounted) {state.setState(() {});}});}@overrideAnimationController getAnimationController(TickerProvider provider) {return AnimationController(duration: Duration(milliseconds: duration), vsync: provider);}@overridevoid init() {}
}///平移动画执行方向枚举
enum TranslationAnimateDirection {///从下往上bottomToTop(90),///从上往下topToBottom(270),///从左往右leftToRight(0),///从右往左rightToLeft(180);///动画执行方向度数final int angle;const TranslationAnimateDirection(this.angle);
}///位移动画类型
enum TranslationAnimateType {///出去动画translateOut,///进入动画translateIn
}


http://www.ppmy.cn/news/1069080.html

相关文章

复数的四则运算(java版)

复数的四则运算&#xff08;java版&#xff09; 目录 复数的四则运算&#xff08;java版&#xff09;介绍复数的四则运算实现思路代码1、封装复数类2、测试复数类3、代码测试结果 介绍 复数&#xff0c;为实数的延伸&#xff0c;它使任一多项式方程都有根。复数当中有个“虚数单…

设计模式—职责链模式(Chain of Responsibility)

目录 思维导图 什么是职责链模式&#xff1f; 有什么优点呢&#xff1f; 有什么缺点呢&#xff1f; 什么场景使用呢&#xff1f; 代码展示 ①、职责链模式 ②、加薪代码重构 思维导图 什么是职责链模式&#xff1f; 使多个对象都有机会处理请求&#xff0c;从而避免请…

day48 动规.p9

- 198.打家劫舍 cpp class Solution { public: int rob(vector<int>& nums) { if (nums.size() 1) return nums[0]; vector<int> dp(nums.size(), 0); dp[0] nums[0]; dp[1] max(nums[0], nums[1]); for (int i 2; i < nums.size(); i) { dp[i] max(…

PDF制作成翻页电子书

在日常工作中&#xff0c;大部分人使用的都是PDF文档发送给客户&#xff0c;但是PDF文档通常是静态的&#xff0c;缺乏交互性和视觉吸引力。那你有没有想过把它转换成翻页的电子书呢&#xff1f; 小编将告诉你操作步骤&#xff0c;非常简单 1.搜索FLBOOK在线制作电子杂志平台 …

大数据Flink实时计算技术

1、架构 2、应用场景 Flink 功能强大&#xff0c;支持开发和运行多种不同种类的应用程序。它的主要特性包括&#xff1a;批流一体化、精密的状态管理、事件时间支持以及精确一次的状态一致性保障等。在启用高可用选项的情况下&#xff0c;它不存在单点失效问题。事实证明&#…

传承精神 缅怀伟人——湖南多链优品科技有限公司赴韶山开展红色主题活动

8月27日上午&#xff0c; 湖南多链优品科技有限公司全体员工怀着崇敬之情&#xff0c;以红色文化为引领&#xff0c;参加了毛泽东同志诞辰130周年的纪念活动。以董事长程小明为核心的公司班子成员以及全国优秀代表近70人一行专赴韶山&#xff0c;缅怀伟人毛泽东同志的丰功伟绩。…

AUTOSAR从入门到精通-【应用篇】基于嵌入式实时Linux及AUTOSAR的跨平台技术研究与实现

目录 前言 通用实时操作系统的国内外研究现状 AUTOSAR国内外研究现状 实时操作系统的选择

React中的性能测试工具组件Profiler的基本使用

React中的性能测试工具组件Profiler是一个非常有用的工具&#xff0c;它可以帮助我们分析React应用程序的性能瓶颈。在本文中&#xff0c;我们将学习如何使用Profiler组件来测试React应用程序的性能。 首先&#xff0c;让我们来了解一下Profiler组件的基本用法。在React中&…