From eb4728e34627a5cc5a0470294ad53ad738bc80a5 Mon Sep 17 00:00:00 2001 From: Jaylen Bian Date: Mon, 2 Aug 2021 15:03:52 +0800 Subject: [PATCH] [infra_ui][overlay] Implement overlap behavior and update example proj --- .../example/lib/overlay/overlay_screen.dart | 39 ++++++-- .../lib/src/flowy_overlay/flowy_overlay.dart | 7 +- .../overlay_layout_delegate.dart | 89 ++++++++++++++++++- 3 files changed, 123 insertions(+), 12 deletions(-) diff --git a/app_flowy/packages/flowy_infra_ui/example/lib/overlay/overlay_screen.dart b/app_flowy/packages/flowy_infra_ui/example/lib/overlay/overlay_screen.dart index ae1b955f01..be6c0fd115 100644 --- a/app_flowy/packages/flowy_infra_ui/example/lib/overlay/overlay_screen.dart +++ b/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( - value: providerContext.watch().anchorDirection, + value: providerContext.watch().anchorDirection, onChanged: (AnchorDirection? newValue) { if (newValue != null) { - providerContext.read().anchorDirection = newValue; + providerContext.read().anchorDirection = newValue; } }, items: AnchorDirection.values.map((AnchorDirection classType) { @@ -91,6 +100,18 @@ class OverlayScreen extends StatelessWidget { }).toList(), ), const SizedBox(height: 24.0), + DropdownButton( + value: providerContext.watch().overlapBehaviour, + onChanged: (OverlapBehaviour? newValue) { + if (newValue != null) { + providerContext.read().overlapBehaviour = newValue; + } + }, + items: OverlapBehaviour.values.map((OverlapBehaviour classType) { + return DropdownMenuItem(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().anchorDirection, + anchorDirection: providerContext.read().anchorDirection, + overlapBehaviour: providerContext.read().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().anchorDirection, + anchorDirection: providerContext.read().anchorDirection, + overlapBehaviour: providerContext.read().overlapBehaviour, ); }, child: const Text('Show Positioned Overlay'), diff --git a/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 7ea0bad9ab..9fd3da09ba 100644 --- a/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/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 { required Size anchorSize, AnchorDirection? anchorDirection, FlowyOverlayDelegate? delegate, + OverlapBehaviour? overlapBehaviour, }) { _showOverlay( widget: widget, @@ -153,6 +153,7 @@ class FlowyOverlayState extends State { anchorPosition: anchorPosition, anchorSize: anchorSize, anchorDirection: anchorDirection, + overlapBehaviour: overlapBehaviour, ); } @@ -162,6 +163,7 @@ class FlowyOverlayState extends State { required BuildContext anchorContext, AnchorDirection? anchorDirection, FlowyOverlayDelegate? delegate, + OverlapBehaviour? overlapBehaviour, }) { _showOverlay( widget: widget, @@ -170,6 +172,7 @@ class FlowyOverlayState extends State { delegate: delegate, anchorContext: anchorContext, anchorDirection: anchorDirection, + overlapBehaviour: overlapBehaviour, ); } diff --git a/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_layout_delegate.dart b/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_layout_delegate.dart index fbf5bca6f7..57b13d0584 100644 --- a/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_layout_delegate.dart +++ b/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; } }