Flutter实现动画列表AnimateListView

这篇具有很好参考价值的文章主要介绍了Flutter实现动画列表AnimateListView。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

功能:

1.可自定义动画。

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

演示:

Flutter实现动画列表AnimateListView,Dart,flutter,flutter,DartFlutter实现动画列表AnimateListView,Dart,flutter,flutter,Dart

代码:

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,
  });

  @override
  State<StatefulWidget> createState() => _KqAnimateListViewState<T>();
}

class _KqAnimateListViewState<T> extends State<KqAnimateListView<T>>
    with TickerProviderStateMixin {
  late IAnimate animate;
  late AnimationController controller;
  late Animation animation;

  @override
  void initState() {
    super.initState();
    animate = widget.animate ?? ScaleAnimate();
    animate.init(widget.data.length);
    controller = animate.getAnimationController(this);
    animation = animate.getAnimation(controller, this);
    //启动动画(正向执行)
    controller.forward();
  }

  @override
  void 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();
    }
  }

  @override
  Widget 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;
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}

///动画抽象类。
///实现该类,定制自己的列表动画。
abstract class IAnimate {
  ///初始化
  ///[length] 列表长度
  void init(int length);

  ///获取AnimationController
  AnimationController getAnimationController(TickerProvider provider);

  ///获取Animation
  Animation getAnimation(
      AnimationController controller, State<StatefulWidget> state);

  ///定制自己的动画,每一个item都会调用到animate,
  ///当需要差异动画时需要根据[index]计算不同item的动画时机
  ///[widget] 执行动画之后的widget
  ///[index] 列表的item的index
  Widget 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});

  @override
  void init(int length) {
    gap = length * twoGap + baseGap;
  }

  @override
  Widget animate(BuildContext context, int index, Widget widget,
      Animation animation, AnimationController controller) {
    double width = context.width;

    ///范围0->1
    double 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,
    );
  }

  @override
  AnimationController getAnimationController(TickerProvider provider) {
    return AnimationController(
        duration: Duration(milliseconds: (gap * rate).toInt()),
        vsync: provider);
  }

  @override
  Animation 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;

  @override
  Widget animate(BuildContext context, int index, Widget widget,
      Animation animation, AnimationController controller) {
    double width = context.width;

    ///范围0.5->1
    double 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,
    );
  }

  @override
  AnimationController getAnimationController(TickerProvider provider) {
    return AnimationController(
        duration: Duration(milliseconds: (gap * rate).toInt()),
        vsync: provider);
  }

  @override
  Animation getAnimation(
      AnimationController controller, State<StatefulWidget> state) {
    return Tween(begin: 0.0, end: gap).animate(controller)
      ..addListener(() {
        if (state.mounted) {
          state.setState(() {});
        }
      });
  }

  @override
  void init(int length) {
    gap = length * twoGap + baseGap;
  }
}

 使用:文章来源地址https://www.toymoban.com/news/detail-670207.html

                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,
                  )

到了这里,关于Flutter实现动画列表AnimateListView的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Flutter】【packages】simple_animations 简单的实现动画

    导入包到项目中去 可以实现简单的动画, 快速实现,不需要自己过多的设置 有多种样式可以实现 [ ] 简单的用例:具体需要详细可以去 pub 链接地址 1. PlayAnimationBuilder 新增child 参数,静态的child ,减少资源的浪费,其他的build 同样可以这样使用 2.LoopAnimationBuilder 循环动画 该用

    2024年02月13日
    浏览(35)
  • Flutter一天一控件之ListTile(列表的实现)

    Flutter中的ListTile控件是一种常用的列表项控件,它可以用于显示列表中的每一个项,通常包含标题、副标题、图标等内容。ListTile控件的外观和行为类似于Android中的ListView中的列表项。 上面的代码中,我们创建了一个ListTile控件,包含一个左侧图标、一个标题、一个副标题和

    2024年02月05日
    浏览(33)
  • Flutter 小技巧之不一样的思路实现炫酷 3D 翻页折叠动画

    今天聊一个比较有意思的 Flutter 动画实现,如果需要实现一个如下图的 3D 折叠动画效果,你会选择通过什么方式? 相信可能很多人第一想法就是: 在 Dart 里通过矩阵变换配合 Canvas 实现 。 因为这个效果其实也算「常见」,在目前的小说阅读器场景里,类似的翻页效果基本都

    2024年02月06日
    浏览(40)
  • 微信小程序 - 实现列表 “滑动删除 / 左滑删除” 动画效果示例源码,在列表上向左滑动右侧出现操作按钮,例如:删除 / 收藏 / 编辑等按钮(点击后自动收回),可一键复制运行代码,详细的代码注释!

    在微信小程序开发中,仿微信列表侧滑删除功能,实现拖住列表左滑时,右侧出现操作按钮功能全部源码, 基础示例功能,你直接复制源码加点样式就行了!~ 复制运行。

    2024年02月15日
    浏览(52)
  • Flutter 笔记 | Flutter 动画

    为了方便开发者创建动画,不同的UI系统对动画都进行了一些抽象, Flutter中也对动画进行了抽象,主要涉及 Animation、Curve、Controller、Tween 这四个角色,它们一起配合来完成一个完整动画,下面我们一一来介绍它们。 1. Animation Animation 是一个抽象类,它本身和UI渲染没有任何关

    2024年02月07日
    浏览(47)
  • Flutter 动画(显式动画、隐式动画、Hero动画、页面转场动画、交错动画)

    当前案例 Flutter SDK版本: 3.13.2 Tween({this.begin,this.end})  两个构造参数,分别是  开始值 和 结束值 ,根据这两个值,提供了控制动画的方法,以下是常用的; controller.forward()   :   向前,执行 begin 到 end 的动画,执行结束后,处于end状态; controller.reverse()   :   反向,当动画

    2024年02月20日
    浏览(49)
  • Flutter(九)Flutter动画和自定义组件

    Animation、Curve、Controller、Tween这四个角色,它们一起配合来完成一个完整动画 Animation Animation是抽象类,和UI渲染没有关系,功能是保存动画的插值和状态;比较常用的是Animation addListener:帧监听器中最常见的行为是改变状态后调用setState()来触发UI重建 addStatusListener:动画开始

    2024年02月10日
    浏览(48)
  • Flutter动画库:animations(路由过渡动画或者页面切换动画)

    animations 是一个 Flutter 库,它提供了一组用于创建动画效果的工具和组件。 这个库的核心重点是路由过渡动画或者页面切换动画 地址 https://pub-web.flutter-io.cn/packages/animations 安装 看了下官方文档和官方例子,然后就有点懵。差点以为找错库了。还好flutter中的库可以直接点开(

    2024年02月16日
    浏览(47)
  • Flutter 06 动画

    1、动画原理: 在任何系统的Ul框架中,动画实现的原理都是相同的,即:在一段时间内,快速地多次改变Ul外观;由于人眼会产生视觉暂留,所以最终看到的就是一个“连续”的动画,这和电影的原理是一样的。 我们将UI的一次改变称为一个动画帧,对应一次屏幕刷新,而决

    2024年02月05日
    浏览(64)
  • Flutter Flar动画实战

    在Flare动面出现之前,Flare动画大体可以分为使用AnimationController控制的基础动画以及使用Hero的转场动画,如果遇到一些复杂的场景,使用这些动画方案实现起来还是有难度的。不过,随着Flutter开始支持Flare矢量动面,Flutter的动画开发也变得越来越简单。事实上,Flare动画是一

    2024年02月14日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包