I have a page like this
I Open an Overlay widget based on the position of each item. i get this position with these codes
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
final RenderBox box = key.currentContext?.findRenderObject() as RenderBox;
position = box.localToGlobal(Offset.zero);
setState(() {});
});
the problem is that when I scroll to top parts of this messaging list offset.dy of that I get from this code is just keeps going down and this offset is not based on the page that is being shown but based on the list.
how can I fix this?
I belive solution presented by boeledi is what you are looking for.
Rect _getPosition(BuildContext context) {
final RenderBox box = context.findRenderObject() as RenderBox;
final Offset topLeft = box.size.topLeft(box.localToGlobal(Offset.zero));
final Offset bottomRight =
box.size.bottomRight(box.localToGlobal(Offset.zero));
return Rect.fromLTRB(
topLeft.dx, topLeft.dy, bottomRight.dx, bottomRight.dy);
}
and translating it by the offset of the Overlay
final Rect widgetPosition = _getPosition(context).translate(
-overlayPosition.left,
-overlayPosition.top,
);
Inside of the widget tree use CustomSingleChildLayout
:
CustomSingleChildLayout(
delegate: _OverlayableContainerLayout(widgetPosition),
child: child,
),
And change position delegate.
class _OverlayableContainerLayout extends SingleChildLayoutDelegate {
_OverlayableContainerLayout(this.position);
final Rect position;
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return BoxConstraints.loose(Size(position.width, position.height));
}
@override
Offset getPositionForChild(Size size, Size childSize) {
return Offset(position.left, position.top);
}
@override
bool shouldRelayout(_OverlayableContainerLayout oldDelegate) {
return position != oldDelegate.position;
}
}