Преглед на файлове

[infra_ui][overlay] Impl hittest and gesture handling interface

Jaylen Bian преди 3 години
родител
ревизия
e7a6a41437

+ 4 - 4
app_flowy/packages/flowy_infra_ui/example/pubspec.lock

@@ -14,7 +14,7 @@ packages:
       name: async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.7.0"
+    version: "2.6.1"
   boolean_selector:
     dependency: transitive
     description:
@@ -35,7 +35,7 @@ packages:
       name: charcode
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.1"
+    version: "1.2.0"
   clock:
     dependency: transitive
     description:
@@ -176,7 +176,7 @@ packages:
       name: meta
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.7.0"
+    version: "1.3.0"
   nested:
     dependency: transitive
     description:
@@ -258,7 +258,7 @@ packages:
       name: test_api
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.4.1"
+    version: "0.3.0"
   textstyle_extensions:
     dependency: transitive
     description:

+ 22 - 0
app_flowy/packages/flowy_infra_ui/lib/src/overlay/overlay_hittest.dart

@@ -0,0 +1,22 @@
+import 'dart:developer';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/rendering.dart';
+
+class OverlayHitTestArea extends SingleChildRenderObjectWidget {
+  const OverlayHitTestArea({
+    Key? key,
+    Widget? child,
+  }) : super(key: key, child: child);
+
+  @override
+  RenderObject createRenderObject(BuildContext context) => RenderOverlayHitTestArea();
+}
+
+class RenderOverlayHitTestArea extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
+  @override
+  bool hitTest(BoxHitTestResult result, {required Offset position}) {
+    print('hitTesting');
+    return super.hitTest(result, position: position);
+  }
+}

+ 57 - 4
app_flowy/packages/flowy_infra_ui/lib/src/overlay/overlay_manager.dart

@@ -1,14 +1,19 @@
 import 'package:flutter/material.dart';
 
+import 'overlay_hittest.dart';
+
 final GlobalKey<OverlayManagerState> _key = GlobalKey<OverlayManagerState>();
+
+/// Invoke this method in app generation process
 TransitionBuilder overlayManagerBuilder() {
   return (context, child) {
     return OverlayManager(key: _key, child: child);
-  }
+  };
 }
 
 class OverlayManager extends StatefulWidget {
   const OverlayManager({Key? key, required this.child}) : super(key: key);
+
   final Widget? child;
 
   static OverlayManagerState of(
@@ -52,9 +57,57 @@ class OverlayManager extends StatefulWidget {
 }
 
 class OverlayManagerState extends State<OverlayManager> {
+  final Map<String, Map<String, OverlayEntry>> _overlayEntrys = {};
+
+  void insert(Widget widget, String featureKey, String key) {
+    final overlay = Overlay.of(context);
+    assert(overlay != null);
+
+    final entry = OverlayEntry(builder: (_) => widget);
+    _overlayEntrys[featureKey] ??= {};
+    _overlayEntrys[featureKey]![key] = entry;
+    overlay!.insert(entry);
+  }
+
+  void insertAll(List<Widget> widgets, String featureKey, List<String> keys) {
+    assert(widgets.isNotEmpty);
+    assert(widgets.length == keys.length);
+
+    final overlay = Overlay.of(context);
+    assert(overlay != null);
+
+    List<OverlayEntry> entries = [];
+    _overlayEntrys[featureKey] ??= {};
+    for (int idx = 0; idx < widgets.length; idx++) {
+      final entry = OverlayEntry(builder: (_) => widget);
+      entries.add(entry);
+      _overlayEntrys[featureKey]![keys[idx]] = entry;
+    }
+    overlay!.insertAll(entries);
+  }
+
+  void remove(String featureKey, String key) {
+    if (_overlayEntrys.containsKey(featureKey)) {
+      final entry = _overlayEntrys[featureKey]!.remove(key);
+      entry?.remove();
+    }
+  }
+
+  void removeAll(String featureKey) {
+    if (_overlayEntrys.containsKey(featureKey)) {
+      final entries = _overlayEntrys.remove(featureKey);
+      entries?.forEach((_, overlay) {
+        overlay.remove();
+      });
+    }
+  }
+
   @override
   Widget build(BuildContext context) {
-    Navigator.of(context, rootNavigator: true);
-    return Container();
+    assert(widget.child != null);
+    return GestureDetector(
+      behavior: HitTestBehavior.translucent,
+      child: OverlayHitTestArea(child: widget.child),
+    );
   }
-}
+}