diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart index 106ac2dca7..03a0a04e2f 100644 --- a/packages/flutter/lib/src/material/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart @@ -752,14 +752,15 @@ class _TabBarState extends State { @override void didUpdateWidget(TabBar oldWidget) { super.didUpdateWidget(oldWidget); - if (widget.controller != oldWidget.controller) + if (widget.controller != oldWidget.controller) { _updateTabController(); - - if (widget.indicatorColor != oldWidget.indicatorColor || + _initIndicatorPainter(); + } else if (widget.indicatorColor != oldWidget.indicatorColor || widget.indicatorWeight != oldWidget.indicatorWeight || widget.indicatorSize != oldWidget.indicatorSize || - widget.indicator != oldWidget.indicator) + widget.indicator != oldWidget.indicator) { _initIndicatorPainter(); + } if (widget.tabs.length > oldWidget.tabs.length) { final int delta = widget.tabs.length - oldWidget.tabs.length; diff --git a/packages/flutter/test/material/tabs_test.dart b/packages/flutter/test/material/tabs_test.dart index a71c460c23..89de8f2f1a 100644 --- a/packages/flutter/test/material/tabs_test.dart +++ b/packages/flutter/test/material/tabs_test.dart @@ -1650,4 +1650,71 @@ void main() { expect(() => new Tab(icon: new Container(), text: 'foo', child: new Container()), throwsAssertionError); expect(() => new Tab(text: 'foo', child: new Container()), throwsAssertionError); }); + + + testWidgets('TabController changes', (WidgetTester tester) async { + // This is a regression test for https://github.com/flutter/flutter/issues/14812 + + Widget buildFrame(TabController controller) { + return boilerplate( + child: new Container( + alignment: Alignment.topLeft, + child: new TabBar( + controller: controller, + tabs: [ + const Tab(text: 'LEFT'), + const Tab(text: 'RIGHT'), + ], + ), + ), + ); + } + + final TabController controller1 = new TabController( + vsync: const TestVSync(), + length: 2, + initialIndex: 0, + ); + + final TabController controller2 = new TabController( + vsync: const TestVSync(), + length: 2, + initialIndex: 0, + ); + + await tester.pumpWidget(buildFrame(controller1)); + await tester.pumpWidget(buildFrame(controller2)); + expect(controller1.index, 0); + expect(controller2.index, 0); + + const double indicatorWeight = 2.0; + final RenderBox tabBarBox = tester.firstRenderObject(find.byType(TabBar)); + expect(tabBarBox.size.height, 48.0); // 48 = _kTabHeight(46) + indicatorWeight(2.0) + + final double indicatorY = 48.0 - indicatorWeight / 2.0; + double indicatorLeft = indicatorWeight / 2.0; + double indicatorRight = 400.0 - indicatorWeight / 2.0; // 400 = screen_width / 2 + expect(tabBarBox, paints..line( + strokeWidth: indicatorWeight, + p1: new Offset(indicatorLeft, indicatorY), + p2: new Offset(indicatorRight, indicatorY), + )); + + await tester.tap(find.text('RIGHT')); + await tester.pumpAndSettle(); + expect(controller1.index, 0); + expect(controller2.index, 1); + + // Verify that the TabBar's _IndicatorPainter is now listening to + // tabController2. + + indicatorLeft = 400.0 + indicatorWeight / 2.0; + indicatorRight = 800.0 - indicatorWeight / 2.0; + expect(tabBarBox, paints..line( + strokeWidth: indicatorWeight, + p1: new Offset(indicatorLeft, indicatorY), + p2: new Offset(indicatorRight, indicatorY), + )); + }); + }