@@ -140,7 +140,14 @@ mixin RenderVisibilityDetectorBase on RenderObject {
140140 }
141141 bool isFirstUpdate = _updates.isEmpty;
142142 _updates[key] = () {
143- _fireCallback (layer, bounds);
143+ if (bounds == null ) {
144+ // This can happen if set onVisibilityChanged was called with a non-null
145+ // value but this render object has not been laid out. In that case,
146+ // it has no size or geometry, and we should not worry about firing
147+ // an update since it never has been visible.
148+ return ;
149+ }
150+ _fireCallback (layer, bounds! );
144151 };
145152 final updateInterval = VisibilityDetectorController .instance.updateInterval;
146153 if (updateInterval == Duration .zero) {
@@ -228,7 +235,9 @@ mixin RenderVisibilityDetectorBase on RenderObject {
228235
229236 /// Used to get the bounds of the render object when it is time to update
230237 /// clients about visibility.
231- Rect get bounds;
238+ ///
239+ /// A null value means bounds are not available.
240+ Rect ? get bounds;
232241
233242 Matrix4 ? _lastPaintTransform;
234243 Rect ? _lastPaintClipBounds;
@@ -280,7 +289,7 @@ class RenderVisibilityDetector extends RenderProxyBox
280289 final Key key;
281290
282291 @override
283- Rect get bounds => semanticBounds;
292+ Rect ? get bounds => hasSize ? semanticBounds : null ;
284293}
285294
286295/// The [RenderObject] corresponding to the [SliverVisibilityDetector] widget.
@@ -302,7 +311,11 @@ class RenderSliverVisibilityDetector extends RenderProxySliver
302311 final Key key;
303312
304313 @override
305- Rect get bounds {
314+ Rect ? get bounds {
315+ if (geometry == null ) {
316+ return null ;
317+ }
318+
306319 Size widgetSize;
307320 Offset widgetOffset;
308321 switch (applyGrowthDirectionToAxisDirection (
0 commit comments