popup_layer.dart 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import 'package:calendar_view/popup_layer/popup_layer_controller.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:get/get.dart';
  4. class PopupLayer extends StatefulWidget {
  5. const PopupLayer({super.key});
  6. @override
  7. State<PopupLayer> createState() => _PopupLayerState();
  8. }
  9. class _PopupLayerState extends State<PopupLayer> {
  10. PopupLayerController popupLayerController = Get.find<PopupLayerController>();
  11. GlobalKey moreSchedulePopupKey = GlobalKey();
  12. @override
  13. void initState() {
  14. super.initState();
  15. popupLayerController.onPopupMoreSchedule.addListener(_onPopupMoreSchedule);
  16. }
  17. @override
  18. void dispose() {
  19. super.dispose();
  20. popupLayerController.onPopupMoreSchedule
  21. .removeListener(_onPopupMoreSchedule);
  22. }
  23. /// 收到显示更多日程的事件
  24. void _onPopupMoreSchedule(e, GlobalKey key) {
  25. setState(() {
  26. moreSchedulePopupKey = key;
  27. });
  28. }
  29. @override
  30. Widget build(BuildContext context) {
  31. return _buildMoreSchedulePopup(moreSchedulePopupKey);
  32. }
  33. /// 只做容器而无需负责内容
  34. /// [trigger] 触发器的 key
  35. Widget _buildMoreSchedulePopup(GlobalKey trigger) {
  36. print('触发了弹出显示更多 Key: $trigger');
  37. final Size triggerSize = getWidgetSize(trigger);
  38. final Offset triggerOffset = getWidgetOffset(trigger);
  39. print('触发者尺寸: $triggerSize');
  40. print('触发者位置: $triggerOffset');
  41. final Offset popupOffset =
  42. _calcPopupLayerOffset(triggerOffset, triggerSize);
  43. print('计算得的弹出层位置: $popupOffset');
  44. return Positioned(
  45. left: triggerOffset.dx,
  46. top: triggerOffset.dy,
  47. child: Container(
  48. decoration: BoxDecoration(
  49. color: Colors.white,
  50. borderRadius: BorderRadius.circular(8),
  51. border: Border.all(color: Colors.black12, width: 1),
  52. /// 简单阴影
  53. boxShadow: const [
  54. BoxShadow(
  55. color: Colors.black12,
  56. offset: Offset(3, 3),
  57. blurRadius: 25,
  58. ),
  59. ],
  60. ),
  61. width: triggerSize.width,
  62. height: 400,
  63. child: Text(popupLayerController.currMoreScheduleData.toString()),
  64. ),
  65. );
  66. }
  67. static const double _popupLayerMarginTop = 70;
  68. static const double _popupLayerMarginLeft = 240;
  69. /// 通过组件的 key 获取对应的组件的大小信息
  70. /// [key] 组件的 key
  71. Size getWidgetSize(GlobalKey key) {
  72. try {
  73. final RenderBox renderBox =
  74. key.currentContext?.findRenderObject() as RenderBox;
  75. return renderBox.size;
  76. } catch (e) {
  77. print('获取大小信息失败: $e');
  78. return Size.zero;
  79. }
  80. }
  81. /// 通过组件的 key 获取对应的组件在弹出层的位置
  82. /// [key] 组件的 key
  83. Offset getWidgetOffset(GlobalKey key) {
  84. try {
  85. final RenderBox renderBox =
  86. key.currentContext?.findRenderObject() as RenderBox;
  87. return renderBox
  88. .localToGlobal(Offset.zero)
  89. .translate(-_popupLayerMarginLeft, -_popupLayerMarginTop);
  90. } catch (e) {
  91. print('获取位置信息失败: $e');
  92. return Offset.zero;
  93. }
  94. }
  95. /// 通过触发者的位置信息和大小信息,计算弹出层的位置信息
  96. /// [triggerOffset] 触发者的位置信息
  97. /// [triggerSize] 触发者的大小信息
  98. Offset _calcPopupLayerOffset(Offset triggerOffset, Size triggerSize) {
  99. final double triggerCenterX = triggerOffset.dx + triggerSize.width / 2;
  100. final double triggerCenterY = triggerOffset.dy + triggerSize.height / 2;
  101. final double popupLayerWidth = 240;
  102. final double popupLayerHeight = 400;
  103. final double popupLayerCenterX = triggerCenterX - popupLayerWidth / 2;
  104. final double popupLayerCenterY = triggerCenterY - popupLayerHeight / 2;
  105. return Offset(popupLayerCenterX, popupLayerCenterY);
  106. }
  107. }