Procházet zdrojové kódy

[infra_ui][overlar] Add overlap behaviour interface and implement part of anchor type

Jaylen Bian před 3 roky
rodič
revize
ada5ab737e

+ 24 - 8
app_flowy/packages/flowy_infra_ui/example/lib/overlay/overlay_screen.dart

@@ -59,13 +59,21 @@ class OverlayScreen extends StatelessWidget {
               return ElevatedButton(
                 onPressed: () {
                   FlowyOverlay.of(context).insertWithAnchor(
-                    widget: const FlutterLogo(
-                      size: 200,
-                      textColor: Colors.orange,
+                    widget: SizedBox(
+                      width: 200,
+                      height: 100,
+                      child: Card(
+                        color: Colors.grey[200],
+                        child: GestureDetector(
+                          onTapDown: (_) => print('Hello Flutter'),
+                          child: const Center(child: FlutterLogo(size: 100)),
+                        ),
+                      ),
                     ),
-                    identifier: 'overlay_flutter_logo',
+                    identifier: 'overlay_card',
                     delegate: null,
                     anchorContext: buttonContext,
+                    anchorDirection: AnchorDirection.topLeft,
                   );
                 },
                 child: const Text('Show Anchored Overlay'),
@@ -76,14 +84,22 @@ class OverlayScreen extends StatelessWidget {
               onPressed: () {
                 final windowSize = MediaQuery.of(context).size;
                 FlowyOverlay.of(context).insertWithRect(
-                  widget: const FlutterLogo(
-                    size: 200,
-                    textColor: Colors.orange,
+                  widget: SizedBox(
+                    width: 200,
+                    height: 100,
+                    child: Card(
+                      color: Colors.orange[200],
+                      child: GestureDetector(
+                        onTapDown: (_) => print('Hello Flutter'),
+                        child: const Center(child: FlutterLogo(size: 100)),
+                      ),
+                    ),
                   ),
-                  identifier: 'overlay_flutter_logo',
+                  identifier: 'overlay_card',
                   delegate: null,
                   anchorPosition: Offset(0, windowSize.height - 200),
                   anchorSize: Size.zero,
+                  anchorDirection: AnchorDirection.topLeft,
                 );
               },
               child: const Text('Show Positioned Overlay'),

+ 16 - 2
app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart

@@ -28,7 +28,18 @@ enum AnchorDirection {
   custom,
 }
 
-/// The behavior of overlay when user tapping system back button
+// TODO: junlin - support overlap behaviour
+/// [Unsupported] The behaviour of overlay when overlap with anchor widget
+enum OverlapBehaviour {
+  /// Maintain overlay size, which may cover the anchor widget.
+  none,
+
+  /// Resize overlay to avoid overlaping the anchor widget.
+  stretch,
+}
+
+// TODO: junlin - support route pop handler
+/// [Unsupported] The behavior of overlay when user tapping system back button
 enum OnBackBehavior {
   /// Won't handle the back action
   none,
@@ -192,6 +203,7 @@ class FlowyOverlayState extends State<FlowyOverlay> {
     Size? anchorSize,
     AnchorDirection? anchorDirection,
     BuildContext? anchorContext,
+    OverlapBehaviour? overlapBehaviour,
     FlowyOverlayDelegate? delegate,
   }) {
     Widget overlay = widget;
@@ -222,7 +234,9 @@ class FlowyOverlayState extends State<FlowyOverlay> {
       overlay = CustomSingleChildLayout(
         delegate: OverlayLayoutDelegate(
           anchorRect: anchorRect,
-          anchorDirection: anchorDirection ?? AnchorDirection.rightWithTopAligned,
+          anchorDirection:
+              shouldAnchor ? anchorDirection ?? AnchorDirection.rightWithTopAligned : AnchorDirection.custom,
+          overlapBehaviour: overlapBehaviour ?? OverlapBehaviour.stretch,
         ),
         child: widget,
       );

+ 27 - 4
app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_layout_delegate.dart

@@ -9,24 +9,47 @@ class OverlayLayoutDelegate extends SingleChildLayoutDelegate {
   OverlayLayoutDelegate({
     required this.anchorRect,
     required this.anchorDirection,
+    required this.overlapBehaviour,
   });
 
   final Rect anchorRect;
   final AnchorDirection anchorDirection;
+  final OverlapBehaviour overlapBehaviour;
 
   @override
   bool shouldRelayout(OverlayLayoutDelegate oldDelegate) {
-    return anchorRect != oldDelegate.anchorRect || anchorDirection != oldDelegate.anchorDirection;
+    return anchorRect != oldDelegate.anchorRect ||
+        anchorDirection != oldDelegate.anchorDirection ||
+        overlapBehaviour != oldDelegate.overlapBehaviour;
   }
 
   @override
   BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
-    return constraints.loosen();
+    switch (overlapBehaviour) {
+      case OverlapBehaviour.none:
+        return constraints.loosen();
+      case OverlapBehaviour.stretch:
+        // TODO: junlin - resize when overlapBehaviour == .stretch
+        return constraints.loosen();
+    }
   }
 
   @override
   Offset getPositionForChild(Size size, Size childSize) {
-    // TODO: junlin - calculate child position
-    return Offset(anchorRect.width / 2, anchorRect.height / 2);
+    Offset position;
+    switch (anchorDirection) {
+      case AnchorDirection.topLeft:
+        position = Offset(
+          anchorRect.left - childSize.width,
+          anchorRect.top - childSize.height,
+        );
+        break;
+      default:
+        throw UnimplementedError();
+    }
+    return Offset(
+      math.max(0.0, math.min(size.width, position.dx)),
+      math.max(0.0, math.min(size.height, position.dy)),
+    );
   }
 }