From 541a8bfd9f8ddfb8b75e92e2af4bf7a4432ea0b6 Mon Sep 17 00:00:00 2001 From: Bruno Leroux Date: Wed, 15 Feb 2023 17:26:50 +0100 Subject: [PATCH] Fix switching from scrollable and non-scrollable tab bars throws (#120771) Co-authored-by: Bruno Leroux --- packages/flutter/lib/src/material/tabs.dart | 2 +- packages/flutter/test/material/tabs_test.dart | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart index afa0fb48f15..5fb8fc7a8ad 100644 --- a/packages/flutter/lib/src/material/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart @@ -1142,7 +1142,7 @@ class _TabBarState extends State { _updateTabController(); _initIndicatorPainter(); // Adjust scroll position. - if (_scrollController != null) { + if (_scrollController != null && _scrollController!.hasClients) { final ScrollPosition position = _scrollController!.position; if (position is _TabBarScrollPosition) { position.markNeedsPixelsCorrection(); diff --git a/packages/flutter/test/material/tabs_test.dart b/packages/flutter/test/material/tabs_test.dart index dc597e301b7..e3689cd8c0a 100644 --- a/packages/flutter/test/material/tabs_test.dart +++ b/packages/flutter/test/material/tabs_test.dart @@ -3568,6 +3568,46 @@ void main() { expect(tester.getCenter(find.byKey(lastTabKey)).dx, equals(750.0)); }); + testWidgets('Do not throw when switching beetween a scrollable TabBar and a non-scrollable TabBar', (WidgetTester tester) async { + // This is a regression test for https://github.com/flutter/flutter/issues/120649 + final TabController controller1 = TabController( + vsync: const TestVSync(), + length: 2, + ); + final TabController controller2 = TabController( + vsync: const TestVSync(), + length: 2, + ); + + Widget buildFrame(TabController controller, bool isScrollable) { + return boilerplate( + child: Container( + alignment: Alignment.topLeft, + child: TabBar( + controller: controller, + isScrollable: isScrollable, + tabs: const [ + Tab(text: 'LEFT'), + Tab(text: 'RIGHT'), + ], + ), + ), + ); + } + + // Show both controllers once. + await tester.pumpWidget(buildFrame(controller1, false)); + await tester.pumpWidget(buildFrame(controller2, true)); + + // Switch back to the first controller. + await tester.pumpWidget(buildFrame(controller1, false)); + expect(tester.takeException(), null); + + // Switch back to the second controller. + await tester.pumpWidget(buildFrame(controller2, true)); + expect(tester.takeException(), null); + }); + testWidgets('Default tab indicator color is white', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/15958 final List tabs = ['LEFT', 'RIGHT'];