mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
[infra_ui][overlar] Implement overlay anchor - widget part
This commit is contained in:
parent
a9c829b417
commit
80cb0f9fa1
@ -45,11 +45,11 @@ class OverlayScreen extends StatelessWidget {
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
FlowyOverlay.of(context).insert(
|
||||
const FlutterLogo(
|
||||
widget: const FlutterLogo(
|
||||
size: 200,
|
||||
),
|
||||
'overlay_flutter_logo',
|
||||
null,
|
||||
identifier: 'overlay_flutter_logo',
|
||||
delegate: null,
|
||||
);
|
||||
},
|
||||
child: const Text('Show Overlay'),
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:dartz/dartz.dart' show Tuple3;
|
||||
import 'package:flowy_infra_ui/src/flowy_overlay/overlay_layout_delegate.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Specifies how overlay are anchored to the SourceWidget
|
||||
@ -110,14 +111,55 @@ class FlowyOverlay extends StatefulWidget {
|
||||
class FlowyOverlayState extends State<FlowyOverlay> {
|
||||
List<Tuple3<Widget, String, FlowyOverlayDelegate?>> _overlayList = [];
|
||||
|
||||
void insert({
|
||||
/// Insert a overlay widget which frame is set by the widget, not the component.
|
||||
/// Be sure to specify the offset and size using the `Postition` widget.
|
||||
void insertCustom({
|
||||
required Widget widget,
|
||||
required String identifier,
|
||||
FlowyOverlayDelegate? delegate,
|
||||
}) {
|
||||
setState(() {
|
||||
_overlayList.add(Tuple3(widget, identifier, delegate));
|
||||
});
|
||||
_showOverlay(
|
||||
widget: widget,
|
||||
identifier: identifier,
|
||||
shouldAnchor: false,
|
||||
delegate: delegate,
|
||||
);
|
||||
}
|
||||
|
||||
void insertWithRect({
|
||||
required Widget widget,
|
||||
required String identifier,
|
||||
required Offset anchorPosition,
|
||||
required Size anchorSize,
|
||||
AnchorDirection? anchorDirection,
|
||||
FlowyOverlayDelegate? delegate,
|
||||
}) {
|
||||
_showOverlay(
|
||||
widget: widget,
|
||||
identifier: identifier,
|
||||
shouldAnchor: true,
|
||||
delegate: delegate,
|
||||
anchorPosition: anchorPosition,
|
||||
anchorSize: anchorSize,
|
||||
anchorDirection: anchorDirection,
|
||||
);
|
||||
}
|
||||
|
||||
void insertWithAnchor({
|
||||
required Widget widget,
|
||||
required String identifier,
|
||||
required BuildContext anchorContext,
|
||||
AnchorDirection? anchorDirection,
|
||||
FlowyOverlayDelegate? delegate,
|
||||
}) {
|
||||
_showOverlay(
|
||||
widget: widget,
|
||||
identifier: identifier,
|
||||
shouldAnchor: true,
|
||||
delegate: delegate,
|
||||
anchorContext: anchorContext,
|
||||
anchorDirection: anchorDirection,
|
||||
);
|
||||
}
|
||||
|
||||
void remove(String identifier) {
|
||||
@ -142,6 +184,48 @@ class FlowyOverlayState extends State<FlowyOverlay> {
|
||||
}
|
||||
}
|
||||
|
||||
void _showOverlay({
|
||||
required Widget widget,
|
||||
required String identifier,
|
||||
required bool shouldAnchor,
|
||||
Offset? anchorPosition,
|
||||
Size? anchorSize,
|
||||
AnchorDirection? anchorDirection,
|
||||
BuildContext? anchorContext,
|
||||
FlowyOverlayDelegate? delegate,
|
||||
}) {
|
||||
Widget overlay = widget;
|
||||
|
||||
if (shouldAnchor) {
|
||||
assert(
|
||||
anchorPosition != null || anchorContext != null,
|
||||
'Must provide `anchorPosition` or `anchorContext` to locating overlay.',
|
||||
);
|
||||
var targetAnchorPosition = anchorPosition;
|
||||
if (anchorContext != null) {
|
||||
RenderObject renderObject = anchorContext.findRenderObject()!;
|
||||
assert(
|
||||
renderObject is RenderBox,
|
||||
'Unexpect non-RenderBox render object caught.',
|
||||
);
|
||||
final localOffset = (renderObject as RenderBox).localToGlobal(Offset.zero);
|
||||
targetAnchorPosition ??= localOffset;
|
||||
}
|
||||
final anchorRect = targetAnchorPosition! & (anchorSize ?? Size.zero);
|
||||
overlay = CustomSingleChildLayout(
|
||||
delegate: OverlayLayoutDelegate(
|
||||
anchorRect: anchorRect,
|
||||
anchorDirection: anchorDirection ?? AnchorDirection.rightWithTopAligned,
|
||||
),
|
||||
child: widget,
|
||||
);
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_overlayList.add(Tuple3(overlay, identifier, delegate));
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final overlays = _overlayList.map((ele) => ele.value1);
|
||||
|
@ -1,43 +1,38 @@
|
||||
// import 'dart:math' as math;
|
||||
// import 'dart:ui';
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui';
|
||||
|
||||
// import 'package:flutter/material.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// import 'flowy_overlay.dart';
|
||||
import 'flowy_overlay.dart';
|
||||
|
||||
// class OverlayLayoutDelegate extends SingleChildLayoutDelegate {
|
||||
// OverlayLayoutDelegate({
|
||||
// required this.route,
|
||||
// required this.padding,
|
||||
// required this.anchorPosition,
|
||||
// required this.anchorDirection,
|
||||
// });
|
||||
class OverlayLayoutDelegate extends SingleChildLayoutDelegate {
|
||||
OverlayLayoutDelegate({
|
||||
required this.anchorRect,
|
||||
required this.anchorDirection,
|
||||
});
|
||||
|
||||
// final OverlayPannelRoute route;
|
||||
// final EdgeInsets padding;
|
||||
// final AnchorDirection anchorDirection;
|
||||
// final Offset anchorPosition;
|
||||
final Rect anchorRect;
|
||||
final AnchorDirection anchorDirection;
|
||||
|
||||
// @override
|
||||
// bool shouldRelayout(OverlayLayoutDelegate oldDelegate) {
|
||||
// return anchorPosition != oldDelegate.anchorPosition || anchorDirection != oldDelegate.anchorDirection;
|
||||
// }
|
||||
@override
|
||||
bool shouldRelayout(OverlayLayoutDelegate oldDelegate) {
|
||||
return anchorRect != oldDelegate.anchorRect || anchorDirection != oldDelegate.anchorDirection;
|
||||
}
|
||||
|
||||
// @override
|
||||
// Offset getPositionForChild(Size size, Size childSize) {
|
||||
// // TODO: junlin - calculate child position
|
||||
// return Offset.zero;
|
||||
// }
|
||||
@override
|
||||
Size getSize(BoxConstraints constraints) {
|
||||
return super.getSize(constraints);
|
||||
}
|
||||
|
||||
// @override
|
||||
// BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
|
||||
// double maxHeight = math.max(0.0, constraints.maxHeight - padding.top - padding.bottom);
|
||||
// double width = constraints.maxWidth;
|
||||
// return BoxConstraints(
|
||||
// minHeight: 0.0,
|
||||
// maxHeight: maxHeight,
|
||||
// minWidth: width,
|
||||
// maxWidth: width,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
@override
|
||||
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
|
||||
// TODO: junlin - calculate child constaints
|
||||
return super.getConstraintsForChild(constraints);
|
||||
}
|
||||
|
||||
@override
|
||||
Offset getPositionForChild(Size size, Size childSize) {
|
||||
// TODO: junlin - calculate child position
|
||||
return Offset(size.width / 2, size.height / 2);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user