floating_items.dart 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // ignore_for_file: must_be_immutable
  2. import 'package:flutter/material.dart';
  3. import 'package:vnoteapp/components/floating_window/floating_item_animated_widget.dart';
  4. import 'package:vnoteapp/components/floating_window/floating_window_shared_data_widget.dart';
  5. /// [FloatingItems] 列表
  6. class FloatingItems extends StatefulWidget {
  7. FloatingItems({Key? key, required this.isEntering}) : super(key: key);
  8. @override
  9. _FloatingItemsState createState() => _FloatingItemsState();
  10. ///[isEntering] 是否具有进场动画
  11. bool isEntering = true;
  12. }
  13. class _FloatingItemsState extends State<FloatingItems>
  14. with TickerProviderStateMixin {
  15. /// [_controller] 列表项动画的控制器
  16. AnimationController? _controller;
  17. /// 动态生成列表
  18. /// 其中一项触发关闭事件后,索引在该项后的列表项执行向上平移的动画。
  19. List<Widget> getItems(BuildContext context) {
  20. /// 释放和申请新的动画资源
  21. if (_controller != null) {
  22. _controller!.dispose();
  23. _controller = AnimationController(
  24. vsync: this, duration: const Duration(milliseconds: 100));
  25. }
  26. /// widget列表
  27. List<Widget> widgetList = [];
  28. /// 获取共享数据
  29. var data = FloatingWindowSharedDataWidget.of(context)!.data;
  30. /// 列表数据
  31. var dataList = data.dataList;
  32. /// 确定列表项位置
  33. double top = data.top + 70.0;
  34. if (data.top + 70.0 * (dataList.length + 1) >
  35. MediaQuery.of(context).size.height - 20.0) {
  36. top = data.top - 70.0 * (dataList.length + 1);
  37. }
  38. /// 遍历数据生成列表项
  39. for (int i = 0; i < dataList.length; ++i) {
  40. /// 在触发关闭事件列表项的索引之后的列表项传入向上平移动画
  41. if (data.deleteIndex != -1 && i >= data.deleteIndex) {
  42. Animation<double> animation;
  43. animation =
  44. Tween<double>(begin: top + (70.0 * (i + 1)), end: top + 70.0 * (i))
  45. .animate(_controller!);
  46. widgetList.add(FloatingItemAnimatedWidget(
  47. upAnimation: animation,
  48. index: i,
  49. isEntering: widget.isEntering,
  50. ));
  51. }
  52. /// 在触发关闭事件列表项的索引之前的列表项则位置固定
  53. else {
  54. Animation<double> animation;
  55. animation =
  56. Tween<double>(begin: top + (70.0 * (i)), end: top + 70.0 * (i))
  57. .animate(_controller!);
  58. widgetList.add(FloatingItemAnimatedWidget(
  59. upAnimation: animation,
  60. index: i,
  61. isEntering: widget.isEntering,
  62. ));
  63. }
  64. }
  65. /// 重置deletedIndex
  66. if (data.deleteIndex != -1) {
  67. data.deleteIndex = -1;
  68. }
  69. /// 执行动画
  70. if (_controller != null) _controller!.forward();
  71. /// 返回列表
  72. return widgetList;
  73. }
  74. @override
  75. void initState() {
  76. // TODO: implement initState
  77. super.initState();
  78. _controller = AnimationController(
  79. vsync: this, duration: const Duration(milliseconds: 100));
  80. }
  81. @override
  82. Widget build(BuildContext context) {
  83. return Stack(
  84. children: getItems(context),
  85. );
  86. }
  87. }