Quellcode durchsuchen

[infra_ui][overlay] Implement overlap behavior and update example proj

Jaylen Bian vor 3 Jahren
Ursprung
Commit
eb4728e346

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

@@ -20,8 +20,8 @@ class OverlayItem extends DemoItem {
   }
 }
 
-class OverlayDemoAnchorDirection extends ChangeNotifier {
-  OverlayDemoAnchorDirection(this._anchorDirection);
+class OverlayDemoConfiguration extends ChangeNotifier {
+  OverlayDemoConfiguration(this._anchorDirection, this._overlapBehaviour);
 
   AnchorDirection _anchorDirection;
 
@@ -31,6 +31,15 @@ class OverlayDemoAnchorDirection extends ChangeNotifier {
     _anchorDirection = value;
     notifyListeners();
   }
+
+  OverlapBehaviour _overlapBehaviour;
+
+  OverlapBehaviour get overlapBehaviour => _overlapBehaviour;
+
+  set overlapBehaviour(OverlapBehaviour value) {
+    _overlapBehaviour = value;
+    notifyListeners();
+  }
 }
 
 class OverlayScreen extends StatelessWidget {
@@ -43,7 +52,7 @@ class OverlayScreen extends StatelessWidget {
           title: const Text('Overlay Demo'),
         ),
         body: ChangeNotifierProvider(
-          create: (context) => OverlayDemoAnchorDirection(AnchorDirection.rightWithTopAligned),
+          create: (context) => OverlayDemoConfiguration(AnchorDirection.rightWithTopAligned, OverlapBehaviour.stretch),
           child: Builder(builder: (providerContext) {
             return Center(
               child: ConstrainedBox(
@@ -80,10 +89,10 @@ class OverlayScreen extends StatelessWidget {
                     ),
                     const SizedBox(height: 24.0),
                     DropdownButton<AnchorDirection>(
-                      value: providerContext.watch<OverlayDemoAnchorDirection>().anchorDirection,
+                      value: providerContext.watch<OverlayDemoConfiguration>().anchorDirection,
                       onChanged: (AnchorDirection? newValue) {
                         if (newValue != null) {
-                          providerContext.read<OverlayDemoAnchorDirection>().anchorDirection = newValue;
+                          providerContext.read<OverlayDemoConfiguration>().anchorDirection = newValue;
                         }
                       },
                       items: AnchorDirection.values.map((AnchorDirection classType) {
@@ -91,6 +100,18 @@ class OverlayScreen extends StatelessWidget {
                       }).toList(),
                     ),
                     const SizedBox(height: 24.0),
+                    DropdownButton<OverlapBehaviour>(
+                      value: providerContext.watch<OverlayDemoConfiguration>().overlapBehaviour,
+                      onChanged: (OverlapBehaviour? newValue) {
+                        if (newValue != null) {
+                          providerContext.read<OverlayDemoConfiguration>().overlapBehaviour = newValue;
+                        }
+                      },
+                      items: OverlapBehaviour.values.map((OverlapBehaviour classType) {
+                        return DropdownMenuItem<OverlapBehaviour>(value: classType, child: Text(classType.toString()));
+                      }).toList(),
+                    ),
+                    const SizedBox(height: 24.0),
                     Builder(builder: (buttonContext) {
                       return SizedBox(
                         height: 100,
@@ -98,7 +119,7 @@ class OverlayScreen extends StatelessWidget {
                           onPressed: () {
                             FlowyOverlay.of(context).insertWithAnchor(
                               widget: SizedBox(
-                                width: 100,
+                                width: 300,
                                 height: 50,
                                 child: Card(
                                   color: Colors.grey[200],
@@ -112,7 +133,8 @@ class OverlayScreen extends StatelessWidget {
                               identifier: 'overlay_anchored_card',
                               delegate: null,
                               anchorContext: buttonContext,
-                              anchorDirection: providerContext.read<OverlayDemoAnchorDirection>().anchorDirection,
+                              anchorDirection: providerContext.read<OverlayDemoConfiguration>().anchorDirection,
+                              overlapBehaviour: providerContext.read<OverlayDemoConfiguration>().overlapBehaviour,
                             );
                           },
                           child: const Text('Show Anchored Overlay'),
@@ -140,7 +162,8 @@ class OverlayScreen extends StatelessWidget {
                           delegate: null,
                           anchorPosition: Offset(0, windowSize.height - 200),
                           anchorSize: Size.zero,
-                          anchorDirection: providerContext.read<OverlayDemoAnchorDirection>().anchorDirection,
+                          anchorDirection: providerContext.read<OverlayDemoConfiguration>().anchorDirection,
+                          overlapBehaviour: providerContext.read<OverlayDemoConfiguration>().overlapBehaviour,
                         );
                       },
                       child: const Text('Show Positioned Overlay'),

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

@@ -28,8 +28,7 @@ enum AnchorDirection {
   custom,
 }
 
-// TODO: junlin - support overlap behaviour
-/// [Unsupported] The behaviour of overlay when overlap with anchor widget
+/// The behaviour of overlay when overlap with anchor widget
 enum OverlapBehaviour {
   /// Maintain overlay size, which may cover the anchor widget.
   none,
@@ -144,6 +143,7 @@ class FlowyOverlayState extends State<FlowyOverlay> {
     required Size anchorSize,
     AnchorDirection? anchorDirection,
     FlowyOverlayDelegate? delegate,
+    OverlapBehaviour? overlapBehaviour,
   }) {
     _showOverlay(
       widget: widget,
@@ -153,6 +153,7 @@ class FlowyOverlayState extends State<FlowyOverlay> {
       anchorPosition: anchorPosition,
       anchorSize: anchorSize,
       anchorDirection: anchorDirection,
+      overlapBehaviour: overlapBehaviour,
     );
   }
 
@@ -162,6 +163,7 @@ class FlowyOverlayState extends State<FlowyOverlay> {
     required BuildContext anchorContext,
     AnchorDirection? anchorDirection,
     FlowyOverlayDelegate? delegate,
+    OverlapBehaviour? overlapBehaviour,
   }) {
     _showOverlay(
       widget: widget,
@@ -170,6 +172,7 @@ class FlowyOverlayState extends State<FlowyOverlay> {
       delegate: delegate,
       anchorContext: anchorContext,
       anchorDirection: anchorDirection,
+      overlapBehaviour: overlapBehaviour,
     );
   }
 

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

@@ -29,8 +29,93 @@ class OverlayLayoutDelegate extends SingleChildLayoutDelegate {
       case OverlapBehaviour.none:
         return constraints.loosen();
       case OverlapBehaviour.stretch:
-        // TODO: junlin - resize when overlapBehaviour == .stretch
-        return constraints.loosen();
+        BoxConstraints childConstraints;
+        switch (anchorDirection) {
+          case AnchorDirection.topLeft:
+            childConstraints = BoxConstraints.loose(Size(
+              anchorRect.left,
+              anchorRect.top,
+            ));
+            break;
+          case AnchorDirection.topRight:
+            childConstraints = BoxConstraints.loose(Size(
+              constraints.maxWidth - anchorRect.right,
+              anchorRect.top,
+            ));
+            break;
+          case AnchorDirection.bottomLeft:
+            childConstraints = BoxConstraints.loose(Size(
+              anchorRect.left,
+              constraints.maxHeight - anchorRect.bottom,
+            ));
+            break;
+          case AnchorDirection.bottomRight:
+            childConstraints = BoxConstraints.loose(Size(
+              constraints.maxWidth - anchorRect.right,
+              constraints.maxHeight - anchorRect.bottom,
+            ));
+            break;
+          case AnchorDirection.rightWithTopAligned:
+            childConstraints = BoxConstraints.loose(Size(
+              constraints.maxWidth - anchorRect.right,
+              constraints.maxHeight - anchorRect.top,
+            ));
+            break;
+          case AnchorDirection.rightWithCenterAligned:
+            childConstraints = BoxConstraints.loose(Size(
+              constraints.maxWidth - anchorRect.right,
+              constraints.maxHeight,
+            ));
+            break;
+          case AnchorDirection.rightWithBottomAligned:
+            childConstraints = BoxConstraints.loose(Size(
+              constraints.maxWidth - anchorRect.right,
+              anchorRect.bottom,
+            ));
+            break;
+          case AnchorDirection.bottomWithLeftAligned:
+            childConstraints = BoxConstraints.loose(Size(
+              anchorRect.left,
+              constraints.maxHeight - anchorRect.bottom,
+            ));
+            break;
+          case AnchorDirection.bottomWithCenterAligned:
+            childConstraints = BoxConstraints.loose(Size(
+              constraints.maxWidth,
+              constraints.maxHeight - anchorRect.bottom,
+            ));
+            break;
+          case AnchorDirection.bottomWithRightAligned:
+            childConstraints = BoxConstraints.loose(Size(
+              anchorRect.right,
+              constraints.maxHeight - anchorRect.bottom,
+            ));
+            break;
+          case AnchorDirection.leftWithTopAligned:
+            childConstraints = BoxConstraints.loose(Size(
+              anchorRect.left,
+              constraints.maxHeight - anchorRect.top,
+            ));
+            break;
+          case AnchorDirection.leftWithCenterAligned:
+            childConstraints = BoxConstraints.loose(Size(
+              anchorRect.left,
+              constraints.maxHeight,
+            ));
+            break;
+          case AnchorDirection.leftWithBottomAligned:
+            childConstraints = BoxConstraints.loose(Size(
+              anchorRect.left,
+              anchorRect.bottom,
+            ));
+            break;
+          case AnchorDirection.custom:
+            childConstraints = constraints.loosen();
+            break;
+          default:
+            throw UnimplementedError();
+        }
+        return childConstraints;
     }
   }