[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(
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'),

View File

@ -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,
);

View File

@ -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) {
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)),
);
}
}