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

This commit is contained in:
Jaylen Bian 2021-08-01 18:53:49 +08:00
parent 58e4a4d5f1
commit ada5ab737e
3 changed files with 67 additions and 14 deletions

View File

@ -59,13 +59,21 @@ class OverlayScreen extends StatelessWidget {
return ElevatedButton( return ElevatedButton(
onPressed: () { onPressed: () {
FlowyOverlay.of(context).insertWithAnchor( FlowyOverlay.of(context).insertWithAnchor(
widget: const FlutterLogo( widget: SizedBox(
size: 200, width: 200,
textColor: Colors.orange, 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, delegate: null,
anchorContext: buttonContext, anchorContext: buttonContext,
anchorDirection: AnchorDirection.topLeft,
); );
}, },
child: const Text('Show Anchored Overlay'), child: const Text('Show Anchored Overlay'),
@ -76,14 +84,22 @@ class OverlayScreen extends StatelessWidget {
onPressed: () { onPressed: () {
final windowSize = MediaQuery.of(context).size; final windowSize = MediaQuery.of(context).size;
FlowyOverlay.of(context).insertWithRect( FlowyOverlay.of(context).insertWithRect(
widget: const FlutterLogo( widget: SizedBox(
size: 200, width: 200,
textColor: Colors.orange, 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, delegate: null,
anchorPosition: Offset(0, windowSize.height - 200), anchorPosition: Offset(0, windowSize.height - 200),
anchorSize: Size.zero, anchorSize: Size.zero,
anchorDirection: AnchorDirection.topLeft,
); );
}, },
child: const Text('Show Positioned Overlay'), child: const Text('Show Positioned Overlay'),

View File

@ -28,7 +28,18 @@ enum AnchorDirection {
custom, 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 { enum OnBackBehavior {
/// Won't handle the back action /// Won't handle the back action
none, none,
@ -192,6 +203,7 @@ class FlowyOverlayState extends State<FlowyOverlay> {
Size? anchorSize, Size? anchorSize,
AnchorDirection? anchorDirection, AnchorDirection? anchorDirection,
BuildContext? anchorContext, BuildContext? anchorContext,
OverlapBehaviour? overlapBehaviour,
FlowyOverlayDelegate? delegate, FlowyOverlayDelegate? delegate,
}) { }) {
Widget overlay = widget; Widget overlay = widget;
@ -222,7 +234,9 @@ class FlowyOverlayState extends State<FlowyOverlay> {
overlay = CustomSingleChildLayout( overlay = CustomSingleChildLayout(
delegate: OverlayLayoutDelegate( delegate: OverlayLayoutDelegate(
anchorRect: anchorRect, anchorRect: anchorRect,
anchorDirection: anchorDirection ?? AnchorDirection.rightWithTopAligned, anchorDirection:
shouldAnchor ? anchorDirection ?? AnchorDirection.rightWithTopAligned : AnchorDirection.custom,
overlapBehaviour: overlapBehaviour ?? OverlapBehaviour.stretch,
), ),
child: widget, child: widget,
); );

View File

@ -9,24 +9,47 @@ class OverlayLayoutDelegate extends SingleChildLayoutDelegate {
OverlayLayoutDelegate({ OverlayLayoutDelegate({
required this.anchorRect, required this.anchorRect,
required this.anchorDirection, required this.anchorDirection,
required this.overlapBehaviour,
}); });
final Rect anchorRect; final Rect anchorRect;
final AnchorDirection anchorDirection; final AnchorDirection anchorDirection;
final OverlapBehaviour overlapBehaviour;
@override @override
bool shouldRelayout(OverlayLayoutDelegate oldDelegate) { bool shouldRelayout(OverlayLayoutDelegate oldDelegate) {
return anchorRect != oldDelegate.anchorRect || anchorDirection != oldDelegate.anchorDirection; return anchorRect != oldDelegate.anchorRect ||
anchorDirection != oldDelegate.anchorDirection ||
overlapBehaviour != oldDelegate.overlapBehaviour;
} }
@override @override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) { 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 @override
Offset getPositionForChild(Size size, Size childSize) { Offset getPositionForChild(Size size, Size childSize) {
// TODO: junlin - calculate child position Offset position;
return Offset(anchorRect.width / 2, anchorRect.height / 2); 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)),
);
} }
} }