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

Flutter实现动画列表AnimateListView

由于业务需要,在打开列表时,列表项需要一个从右边飞入的动画效果,故封装一个专门可以执行动画的列表组件,可以自定义自己的动画,内置有水平滑动,缩放等简单动画。花里胡哨的动画效果由你自己来定制吧。

功能:

1.可自定义动画。

2.内置水平滑动和缩放动画。

演示:

代码:

import 'dart:math';import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';///可设置动画的列表。
///内部使用的是[SingleChildScrollView]实现,
///需要外层设置定义可约束高度。
class KqAnimateListView<T> extends StatefulWidget {///数据final List<T> data;///列表final Widget Function(T t) item;///动画自定义final IAnimate? animate;///是否需要每次刷新时都执行动画final bool isNeedFlashEveryTime;const KqAnimateListView({super.key,required this.item,required this.data,this.animate,this.isNeedFlashEveryTime = false,});@overrideState<StatefulWidget> createState() => _KqAnimateListViewState<T>();
}class _KqAnimateListViewState<T> extends State<KqAnimateListView<T>>with TickerProviderStateMixin {late IAnimate animate;late AnimationController controller;late Animation animation;@overridevoid initState() {super.initState();animate = widget.animate ?? ScaleAnimate();animate.init(widget.data.length);controller = animate.getAnimationController(this);animation = animate.getAnimation(controller, this);//启动动画(正向执行)controller.forward();}@overridevoid didUpdateWidget(covariant KqAnimateListView<T> oldWidget) {super.didUpdateWidget(oldWidget);if (widget.isNeedFlashEveryTime) {animate = widget.animate ?? ScaleAnimate();animate.init(widget.data.length);controller = animate.getAnimationController(this);animation = animate.getAnimation(controller, this);//启动动画(正向执行)controller.forward();}}@overrideWidget build(BuildContext context) {return SizedBox.expand(child: SingleChildScrollView(child: Column(children: _getChildren(context),),),);}List<Widget> _getChildren(BuildContext context) {List<Widget> list = [];for (int i = 0; i < widget.data.length; i++) {Widget child = widget.item.call(widget.data[i]);list.add(animate.animate(context, i, child, animation, controller),);}return list;}@overridevoid dispose() {controller.dispose();super.dispose();}
}///动画抽象类。
///实现该类,定制自己的列表动画。
abstract class IAnimate {///初始化///[length] 列表长度void init(int length);///获取AnimationControllerAnimationController getAnimationController(TickerProvider provider);///获取AnimationAnimation getAnimation(AnimationController controller, State<StatefulWidget> state);///定制自己的动画,每一个item都会调用到animate,///当需要差异动画时需要根据[index]计算不同item的动画时机///[widget] 执行动画之后的widget///[index] 列表的item的indexWidget animate(BuildContext context,int index,Widget widget,Animation animation,AnimationController controller,);
}///水平移动动画
class HorizontalAnimate extends IAnimate {///动画执行时长比例static double rate = 0.4;///单个动画执行长度static double baseGap = 1000.0;///两个个动画执行间隔长度static double twoGap = 200.0;///动画执行的总长度,根据列表长度动态计算值late double gap;///动画是从左边还是右边开始执行HorizontalAnimateDirection direction;HorizontalAnimate({this.direction = HorizontalAnimateDirection.right});@overridevoid init(int length) {gap = length * twoGap + baseGap;}@overrideWidget animate(BuildContext context, int index, Widget widget,Animation animation, AnimationController controller) {double width = context.width;///范围0->1double mix = (animation.value - twoGap * index) / baseGap;if (mix > 1) {mix = 1;}double left = width * (1 - mix);return Container(transform: Matrix4.translationValues(direction == HorizontalAnimateDirection.left ? -left : left, 0, 0),child: widget,);}@overrideAnimationController getAnimationController(TickerProvider provider) {return AnimationController(duration: Duration(milliseconds: (gap * rate).toInt()),vsync: provider);}@overrideAnimation getAnimation(AnimationController controller, State<StatefulWidget> state) {return Tween(begin: 0.0, end: gap).animate(controller)..addListener(() {if (state.mounted) {state.setState(() {});}});}
}enum HorizontalAnimateDirection {///左边left,///右边right;
}///缩放动画
class ScaleAnimate extends IAnimate {///动画执行时长比例static double rate = 0.4;///单个动画执行长度static double baseGap = 1000.0;///两个个动画执行间隔长度static double twoGap = 200.0;///动画执行的总长度,根据列表长度动态计算值late double gap;@overrideWidget animate(BuildContext context, int index, Widget widget,Animation animation, AnimationController controller) {double width = context.width;///范围0.5->1double mix = ((animation.value - twoGap * index) / baseGap + 1) / 2;if (mix > 1) {mix = 1;}double widthMix = width * mix;return SizedBox(width: max(0, widthMix),child: widget,);}@overrideAnimationController getAnimationController(TickerProvider provider) {return AnimationController(duration: Duration(milliseconds: (gap * rate).toInt()),vsync: provider);}@overrideAnimation getAnimation(AnimationController controller, State<StatefulWidget> state) {return Tween(begin: 0.0, end: gap).animate(controller)..addListener(() {if (state.mounted) {state.setState(() {});}});}@overridevoid init(int length) {gap = length * twoGap + baseGap;}
}

 使用:

                KqAnimateListView(data: const ["Test1","Test2","Test3","Test3","Test3","Test3","Test3","Test3","Test3","Test3","Test3","Test3","Test3"],item: (t) {return Container(width: double.infinity,height: 50,color: Colors.redAccent,margin: EdgeInsets.only(top: 10.r),child: Text(t),);},animate: type == 0? HorizontalAnimate(direction: HorizontalAnimateDirection.left): type == 1? HorizontalAnimate(direction: HorizontalAnimateDirection.right): ScaleAnimate(),isNeedFlashEveryTime: true,)

http://www.lryc.cn/news/147980.html

相关文章:

  • 【LeetCode-中等题】236. 二叉树的最近公共祖先
  • 如何拼接两个视频在一起?
  • Programming abstractions in C阅读笔记:p130-p131
  • 如何在Windows本地快速搭建SFTP文件服务器,并通过端口映射实现公网远程访问
  • C#---第二十:不同类型方法的执行顺序(new / virtual / common / override)
  • lnmp架构-PHP
  • 【javascript实操记录】
  • Mysql--技术文档--悲观锁、乐观锁-《控制并发机制简单认知、深度理解》
  • 【GO】LGTM_Grafana_Tempo(2)_官方用例改后实操
  • git 口令
  • 【回眸】剑指offer(二)解题思路
  • Python 基本文件操作及os库
  • YOLOv5算法改进(9)— 替换主干网络之ShuffleNetV2
  • 三、mycat分库分表
  • gitlab提交项目Log in with Access Token错误
  • openGauss学习笔记-56 openGauss 高级特性-DCF
  • Xcode 14 pod init报错
  • 飞腾PSPA可信启动--2 数字签名证书
  • 微前端:重塑大型项目的前沿技术
  • 官方推荐使用的OkHttp4网络请求库全面解析(Android篇)
  • Spooling的原理
  • Homebrew 无法安装过时的PHP版本
  • python爬取bilibili,下载视频
  • java八股文面试[多线程]——进程与线程的区别
  • SpringBootWeb 登录认证[Cookie + Session + Token + Filter + Interceptor]
  • d3dcompiler_43.dll丢失怎么修复,分享几种修复d3dcompiler_43.dll的方法
  • mqtt集群搭建并使用nginx做负载均衡_亲测得结论
  • JavaScript—DOM(文档对象模型)
  • mysql Index
  • ​八路参考文献:[八一新书]许少辉.乡村振兴战略下传统村落文化旅游设计[M]北京:中国建筑出版传媒,2022.