浏览代码

实现全局点击监听

gavin.chen 2 年之前
父节点
当前提交
caa7800c3a

+ 6 - 2
lib/calendar_page/calendar_page.dart

@@ -1,6 +1,8 @@
 import 'package:calendar_view/calendar_controller/controller.dart';
 import 'package:calendar_view/calendar_page/calendar_left_panel.dart';
 import 'package:calendar_view/calendar_page/calendar_main_panel.dart';
+import 'package:calendar_view/popup_layer/global_click_listener.dart';
+import 'package:calendar_view/popup_layer/popup_layer_controller.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 
@@ -12,6 +14,8 @@ class CalendarPage extends StatefulWidget {
 }
 
 class _CalendarPageState extends State<CalendarPage> {
+  final PopupLayerController _popupLayerController =
+      Get.put<PopupLayerController>(PopupLayerController());
   @override
   void initState() {
     super.initState();
@@ -20,8 +24,8 @@ class _CalendarPageState extends State<CalendarPage> {
 
   @override
   Widget build(BuildContext context) {
-    return Container(
-      // color: Color.fromARGB(90, 255, 235, 59),
+    return GlobalClickListener(
+      controller: _popupLayerController,
       child: Row(
         children: const <Widget>[
           CalendarLeftPanel(),

+ 1 - 1
lib/calendar_page/month_calendar/month_calendar_item.dart

@@ -32,7 +32,7 @@ class _MyWidgetState extends State<MonthDayItem> {
   );
   late TextStyle _dayTextStyle;
   late TextStyle _lunarDayTextStyle;
-  GlobalKey _monthGridKey = GlobalKey();
+  final GlobalKey _monthGridKey = GlobalKey();
 
   /// TODO[Gavin]: i18n
   get displayStr => _dayData.isToday ? '今' : _dayData.date.day.toString();

+ 14 - 4
lib/calendar_page/month_calendar/more_schedule_popup.dart

@@ -1,6 +1,8 @@
+import 'package:calendar_view/calendar_controller/controller.dart';
 import 'package:calendar_view/utils/calendar_util.dart';
 import 'package:calendar_view/utils/chinese_calendar_utils.dart';
 import 'package:flutter/material.dart';
+import 'package:get/get.dart';
 
 class MoreSchedulePopup extends StatefulWidget {
   const MoreSchedulePopup({
@@ -17,6 +19,15 @@ class MoreSchedulePopup extends StatefulWidget {
 
 class MoreSchedulePopupState extends State<MoreSchedulePopup> {
   static const double _itemHeight = 28;
+  List<Schedule> _scheduleDataList = [];
+  CalendarController calendarController = Get.find<CalendarController>();
+
+  @override
+  void initState() {
+    super.initState();
+    _scheduleDataList =
+        calendarController.scheduleListFilter(widget.scheduleData.scheduleList);
+  }
 
   @override
   Widget build(BuildContext context) {
@@ -62,7 +73,7 @@ class MoreSchedulePopupState extends State<MoreSchedulePopup> {
       addAutomaticKeepAlives: false,
       addRepaintBoundaries: true,
       itemExtent: _itemHeight,
-      itemCount: widget.scheduleData.scheduleList.length,
+      itemCount: _scheduleDataList.length,
       itemBuilder: (context, index) {
         return _buildScheduleTypeItem(index);
       },
@@ -70,9 +81,8 @@ class MoreSchedulePopupState extends State<MoreSchedulePopup> {
   }
 
   Widget _buildScheduleTypeItem(int scheduleIndex) {
-    ScheduleType scheduleType =
-        widget.scheduleData.scheduleList[scheduleIndex].type;
-    Schedule schedule = widget.scheduleData.scheduleList[scheduleIndex];
+    ScheduleType scheduleType = _scheduleDataList[scheduleIndex].type;
+    Schedule schedule = _scheduleDataList[scheduleIndex];
     return Material(
       color: Colors.transparent,
       child: InkWell(

+ 0 - 2
lib/calendar_page/month_calendar/schedule_list.dart

@@ -30,8 +30,6 @@ class ScheduleList extends StatefulWidget {
 class ScheduleListState extends State<ScheduleList> {
   /// 容纳的数量
   int _itemCount = 0;
-  PopupLayerController popupLayerController = Get.find<PopupLayerController>();
-
   @override
   void initState() {
     super.initState();

+ 27 - 0
lib/popup_layer/global_click_listener.dart

@@ -0,0 +1,27 @@
+import 'package:calendar_view/popup_layer/popup_layer_controller.dart';
+import 'package:flutter/material.dart';
+
+/// 全局事件监听器,用于搭配popup_layer使用
+/// 用于监听全局点击事件,当点击到popup_layer以外的区域时,关闭popup_layer
+class GlobalClickListener extends StatelessWidget {
+  const GlobalClickListener(
+      {Key? key, required this.child, required this.controller})
+      : super(key: key);
+
+  final Widget child;
+  final PopupLayerController controller;
+
+  @override
+  Widget build(BuildContext context) {
+    return Listener(
+      behavior: HitTestBehavior.translucent,
+      onPointerDown: (event) {
+        controller.onGlobalClick.emit(this, event);
+      },
+      onPointerUp: (event) {
+        controller.onGlobalClick.emit(this, event);
+      },
+      child: child,
+    );
+  }
+}

+ 21 - 4
lib/popup_layer/popup_layer.dart

@@ -15,11 +15,13 @@ class PopupLayer extends StatefulWidget {
 class _PopupLayerState extends State<PopupLayer> {
   PopupLayerController popupLayerController = Get.find<PopupLayerController>();
   bool _isShowPopup = false;
+  bool _isNeedClosePopup = false;
   GlobalKey moreSchedulePopupKey = GlobalKey();
   @override
   void initState() {
     super.initState();
     popupLayerController.onPopupMoreSchedule.addListener(_onPopupMoreSchedule);
+    popupLayerController.onGlobalClick.addListener(_onGlobalClick);
   }
 
   @override
@@ -27,6 +29,7 @@ class _PopupLayerState extends State<PopupLayer> {
     super.dispose();
     popupLayerController.onPopupMoreSchedule
         .removeListener(_onPopupMoreSchedule);
+    popupLayerController.onGlobalClick.removeListener(_onGlobalClick);
   }
 
   /// 收到显示更多日程的事件
@@ -37,15 +40,29 @@ class _PopupLayerState extends State<PopupLayer> {
     });
   }
 
+  /// 收到全局点击事件
+  /// 全局按下时设置 _needClosePopup 为 true
+  /// 弹层组件收到 onPointerUp 时设置 _needClosePopup 为 false
+  /// 全局抬起时判断 _needClosePopup 是否为 true,为 true 则关闭弹层
+  void _onGlobalClick(e, PointerEvent event) {
+    if (event is PointerDownEvent) {
+      _isNeedClosePopup = true;
+    } else if (event is PointerUpEvent) {
+      if (_isNeedClosePopup) {
+        setState(() {
+          _isShowPopup = false;
+        });
+      }
+    }
+  }
+
   @override
   Widget build(BuildContext context) {
     return _isShowPopup
         ? Listener(
-            behavior: HitTestBehavior.translucent,
+            behavior: HitTestBehavior.deferToChild,
             onPointerUp: (event) {
-              setState(() {
-                _isShowPopup = false;
-              });
+              _isNeedClosePopup = false;
             },
             child: _buildMoreSchedulePopup(moreSchedulePopupKey),
           )

+ 3 - 0
lib/popup_layer/popup_layer_controller.dart

@@ -9,6 +9,9 @@ class PopupLayerController extends GetxController {
   /// 弹出层【显示更多日程】事件通知
   FEventHandler<GlobalKey> onPopupMoreSchedule = FEventHandler<GlobalKey>();
 
+  /// 全局点击事件通知
+  FEventHandler<PointerEvent> onGlobalClick = FEventHandler<PointerEvent>();
+
   /// Popup 弹出层相关的数据
   /// 当前需要显示更多的日程数据
   MonthViewDayStructure currMoreScheduleData = MonthViewDayStructure(