Update TabBar indicator painter when tab controller changes (#14825)

diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart
index 106ac2d..03a0a04 100644
--- a/packages/flutter/lib/src/material/tabs.dart
+++ b/packages/flutter/lib/src/material/tabs.dart
@@ -752,14 +752,15 @@
   @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 a71c460..89de8f2 100644
--- a/packages/flutter/test/material/tabs_test.dart
+++ b/packages/flutter/test/material/tabs_test.dart
@@ -1650,4 +1650,71 @@
     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: <Tab>[
+              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<RenderBox>(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),
+    ));
+  });
+
 }