From ada5ab737e9c353a106dc87a5bd1060c78fd34d7 Mon Sep 17 00:00:00 2001 From: Jaylen Bian Date: Sun, 1 Aug 2021 18:53:49 +0800 Subject: [PATCH] [infra_ui][overlar] Add overlap behaviour interface and implement part of anchor type --- .../example/lib/overlay/overlay_screen.dart | 32 ++++++++++++++----- .../lib/src/flowy_overlay/flowy_overlay.dart | 18 +++++++++-- .../overlay_layout_delegate.dart | 31 +++++++++++++++--- 3 files changed, 67 insertions(+), 14 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 5c5738dc11..ffb702816d 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 @@ -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'), 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 269eb8aa1f..a12988f0a5 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,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 { Size? anchorSize, AnchorDirection? anchorDirection, BuildContext? anchorContext, + OverlapBehaviour? overlapBehaviour, FlowyOverlayDelegate? delegate, }) { Widget overlay = widget; @@ -222,7 +234,9 @@ class FlowyOverlayState extends State { overlay = CustomSingleChildLayout( delegate: OverlayLayoutDelegate( anchorRect: anchorRect, - anchorDirection: anchorDirection ?? AnchorDirection.rightWithTopAligned, + anchorDirection: + shouldAnchor ? anchorDirection ?? AnchorDirection.rightWithTopAligned : AnchorDirection.custom, + overlapBehaviour: overlapBehaviour ?? OverlapBehaviour.stretch, ), child: widget, ); 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 eaea7c17f8..b09eb3a28e 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 @@ -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)), + ); } }