Skip to content

Instantly share code, notes, and snippets.

@tarek360
Created March 15, 2023 17:09
Show Gist options
  • Save tarek360/1e0695ec9cdf8c6659830efa264e60cd to your computer and use it in GitHub Desktop.
Save tarek360/1e0695ec9cdf8c6659830efa264e60cd to your computer and use it in GitHub Desktop.
RelativePositionOverlay to show a context popup in a position relative to the another widget position
class RelativePositionOverlay extends StatefulWidget {
const RelativePositionOverlay({
super.key,
required this.popupBuilder,
required this.child,
this.popupOffset = Offset.zero,
});
final WidgetBuilder popupBuilder;
final Widget child;
final Offset popupOffset;
@override
State<RelativePositionOverlay> createState() => _RelativePositionOverlayState();
}
class _RelativePositionOverlayState extends State<RelativePositionOverlay> {
final FocusNode _focusNode = FocusNode();
late OverlayEntry _overlayEntry;
final LayerLink _layerLink = LayerLink();
@override
void initState() {
super.initState();
_focusNode.addListener(() {
if (_focusNode.hasFocus) {
_overlayEntry = _createOverlayEntry();
Overlay.of(context).insert(_overlayEntry);
} else {
_overlayEntry.remove();
}
});
}
OverlayEntry _createOverlayEntry() {
return OverlayEntry(
builder: (context) => Positioned(
left: 0,
child: CompositedTransformFollower(
link: _layerLink,
showWhenUnlinked: false,
offset: widget.popupOffset,
child: widget.popupBuilder(context),
),
));
}
@override
Widget build(BuildContext context) {
return CompositedTransformTarget(
link: _layerLink,
child: Focus(
focusNode: _focusNode,
child: widget.child,
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment