diff --git a/packages/flutter/lib/src/rendering/sliver_grid.dart b/packages/flutter/lib/src/rendering/sliver_grid.dart index cb44d4a8b9f..26847e24b55 100644 --- a/packages/flutter/lib/src/rendering/sliver_grid.dart +++ b/packages/flutter/lib/src/rendering/sliver_grid.dart @@ -658,7 +658,6 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor { leadingScrollOffset: leadingScrollOffset, trailingScrollOffset: trailingScrollOffset, ); - final double paintExtent = calculatePaintOffset( constraints, from: math.min(constraints.scrollOffset, leadingScrollOffset), @@ -675,8 +674,7 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor { paintExtent: paintExtent, maxPaintExtent: estimatedTotalExtent, cacheExtent: cacheExtent, - // Conservative to avoid complexity. - hasVisualOverflow: true, + hasVisualOverflow: estimatedTotalExtent > paintExtent || constraints.scrollOffset > 0.0 || constraints.overlap != 0.0, ); // We may have started the layout while scrolled to the end, which diff --git a/packages/flutter/test/widgets/grid_view_test.dart b/packages/flutter/test/widgets/grid_view_test.dart index 21ce43915ac..bbd8ee923c3 100644 --- a/packages/flutter/test/widgets/grid_view_test.dart +++ b/packages/flutter/test/widgets/grid_view_test.dart @@ -645,13 +645,50 @@ void main() { expect(counters[4], 2); }); + testWidgets('GridView does not report visual overflow unnecessarily', (WidgetTester tester) async { + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: GridView( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3), + children: [ + Container(height: 200.0), + ], + ), + ), + ); + + // 1st, check that the render object has received the default clip behavior. + final RenderViewport renderObject = tester.allRenderObjects.whereType().first; + expect(renderObject.clipBehavior, equals(Clip.hardEdge)); + + // The context will get Clip.none because there is no actual visual overflow. + final TestClipPaintingContext context = TestClipPaintingContext(); + renderObject.paint(context, Offset.zero); + expect(context.clipBehavior, equals(Clip.none)); + }); + testWidgets('GridView respects clipBehavior', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: GridView( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3), - children: [Container(height: 2000.0)], + children: [ + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + ], ), ), ); @@ -672,7 +709,21 @@ void main() { child: GridView( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3), clipBehavior: Clip.antiAlias, - children: [Container(height: 2000.0)], + children: [ + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + Container(height: 2000.0), + ], ), ), );