From d8100ac5ed3f597757b031de45dcebc3cd0542ca Mon Sep 17 00:00:00 2001 From: Navaron Bracke Date: Wed, 26 Feb 2025 19:39:26 +0100 Subject: [PATCH] Guard against zero item extent for carousel (#163310) This PR fixes a bug where the `CarouselView` would throw an error if the itemExtent is zero. Part of https://github.com/flutter/flutter/issues/160679 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --- .../flutter/lib/src/material/carousel.dart | 12 ++++++++++++ .../flutter/test/material/carousel_test.dart | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/packages/flutter/lib/src/material/carousel.dart b/packages/flutter/lib/src/material/carousel.dart index 59900eb9ff9f3..71957e79af430 100644 --- a/packages/flutter/lib/src/material/carousel.dart +++ b/packages/flutter/lib/src/material/carousel.dart @@ -579,6 +579,10 @@ class _RenderSliverFixedExtentCarousel extends RenderSliverFixedExtentBoxAdaptor // This implements the [itemExtentBuilder] callback. double _buildItemExtent(int index, SliverLayoutDimensions currentLayoutDimensions) { + if (maxExtent == 0.0) { + return maxExtent; + } + final int firstVisibleIndex = (constraints.scrollOffset / maxExtent).floor(); // Calculate how many items have been completely scroll off screen. @@ -641,6 +645,10 @@ class _RenderSliverFixedExtentCarousel extends RenderSliverFixedExtentBoxAdaptor double itemExtent, int index, ) { + if (maxExtent == 0.0) { + return maxExtent; + } + final int firstVisibleIndex = (constraints.scrollOffset / maxExtent).floor(); // If there is not enough space to place the last visible item but the remaining @@ -673,6 +681,10 @@ class _RenderSliverFixedExtentCarousel extends RenderSliverFixedExtentBoxAdaptor ) double itemExtent, ) { + if (maxExtent == 0.0) { + return 0; + } + final int firstVisibleIndex = (constraints.scrollOffset / maxExtent).floor(); return math.max(firstVisibleIndex, 0); } diff --git a/packages/flutter/test/material/carousel_test.dart b/packages/flutter/test/material/carousel_test.dart index 9784d767a7629..dd0a9bac55a47 100644 --- a/packages/flutter/test/material/carousel_test.dart +++ b/packages/flutter/test/material/carousel_test.dart @@ -1413,6 +1413,25 @@ void main() { expect(buttonPressed, isTrue); }, ); + + // Regression test for https://github.com/flutter/flutter/issues/160679 + testWidgets('CarouselView does not crash if itemExtent is zero', (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: SizedBox( + width: 100, + child: CarouselView( + itemExtent: 0, + children: [Container(color: Colors.red, width: 100, height: 100)], + ), + ), + ), + ), + ); + + expect(tester.takeException(), isNull); + }); } Finder getItem(int index) {