Created
July 28, 2021 19:45
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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