Skip to content

Instantly share code, notes, and snippets.

@lslv1243
Created July 28, 2021 19:45
Show Gist options
  • Save lslv1243/778c0bbe635f5b6c6b5f3fbf166be146 to your computer and use it in GitHub Desktop.
Save lslv1243/778c0bbe635f5b6c6b5f3fbf166be146 to your computer and use it in GitHub Desktop.
Can be used to enable touch events to happen in a Positioned widget which is outside of the stack boundaries.
class PositionedOverlayEntry extends StatefulWidget {
final OverlayState overlay;
final Widget child;
final double? left;
final double? top;
final double? right;
final double? bottom;
final double? width;
final double? height;
const PositionedOverlayEntry({
Key? key,
required this.overlay,
this.left,
this.top,
this.right,
this.bottom,
this.width,
this.height,
required this.child,
}) : super(key: key);
@override
_PositionedOverlayEntryState createState() => _PositionedOverlayEntryState();
}
class _PositionedOverlayEntryState extends State<PositionedOverlayEntry> {
late final OverlayEntry _overlayEntry;
final _childKey = GlobalKey();
Offset? _topLeft;
Offset? _bottomRight;
@override
void initState() {
super.initState();
_overlayEntry = OverlayEntry(builder: _overlayBuilder);
WidgetsBinding.instance!.addPostFrameCallback((_) {
_measure();
widget.overlay.insert(_overlayEntry);
});
}
@override
void dispose() {
_overlayEntry.remove();
super.dispose();
}
void _measure() {
final stackRenderBox = context.findRenderObject()!.parent as RenderBox;
final overlayRenderBox =
widget.overlay.context.findRenderObject() as RenderBox;
Offset stackToOverlay(Offset offset) {
return overlayRenderBox
.globalToLocal(stackRenderBox.localToGlobal(offset));
}
var topLeft = Offset.zero;
topLeft = stackToOverlay(topLeft);
var bottomRight = Offset(
stackRenderBox.size.width,
stackRenderBox.size.height,
);
bottomRight = stackToOverlay(bottomRight);
bottomRight = Offset(
bottomRight.dx - overlayRenderBox.size.width,
bottomRight.dy - overlayRenderBox.size.height,
);
setState(() {
_topLeft = topLeft;
_bottomRight = bottomRight;
});
}
Widget _buildChild(BuildContext context) {
return KeyedSubtree(
key: _childKey,
child: widget.child,
);
}
Widget _overlayBuilder(BuildContext context) {
double? top;
double? left;
double? bottom;
double? right;
if (widget.top != null) top = widget.top! + _topLeft!.dy;
if (widget.left != null) left = widget.left! + _topLeft!.dx;
if (widget.bottom != null) bottom = widget.bottom! - _bottomRight!.dy;
if (widget.right != null) right = widget.right! - _bottomRight!.dx;
return Positioned(
top: top,
left: left,
bottom: bottom,
right: right,
width: widget.width,
height: widget.height,
child: _buildChild(context),
);
}
@override
Widget build(BuildContext context) {
return Positioned(
left: widget.left,
top: widget.top,
right: widget.right,
bottom: widget.bottom,
width: widget.width,
height: widget.height,
child: _topLeft == null ? _buildChild(context) : SizedBox(),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment