Unverified Commit 2ce43fac authored by xubaolin's avatar xubaolin Committed by GitHub

Fix a Tabs crash when change the TabControllers (#98242)

parent 83a88058
...@@ -1420,7 +1420,9 @@ class _TabBarViewState extends State<TabBarView> { ...@@ -1420,7 +1420,9 @@ class _TabBarViewState extends State<TabBarView> {
if (widget.controller != oldWidget.controller) { if (widget.controller != oldWidget.controller) {
_updateTabController(); _updateTabController();
_currentIndex = _controller!.index; _currentIndex = _controller!.index;
_warpUnderwayCount += 1;
_pageController.jumpToPage(_currentIndex!); _pageController.jumpToPage(_currentIndex!);
_warpUnderwayCount -= 1;
} }
if (widget.children != oldWidget.children && _warpUnderwayCount == 0) if (widget.children != oldWidget.children && _warpUnderwayCount == 0)
_updateChildren(); _updateChildren();
......
...@@ -4253,7 +4253,7 @@ void main() { ...@@ -4253,7 +4253,7 @@ void main() {
testWidgets('Change the TabController should make both TabBar and TabBarView return to the initial index.', (WidgetTester tester) async { testWidgets('Change the TabController should make both TabBar and TabBarView return to the initial index.', (WidgetTester tester) async {
// This is a regression test for https://github.com/flutter/flutter/issues/93237 // This is a regression test for https://github.com/flutter/flutter/issues/93237
Widget buildFrame(TabController controller, bool showLast) { Widget buildFrame(TabController controller, {required bool showLast}) {
return boilerplate( return boilerplate(
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
...@@ -4295,23 +4295,22 @@ void main() { ...@@ -4295,23 +4295,22 @@ void main() {
length: 3, length: 3,
); );
await tester.pumpWidget(buildFrame(controller1, true)); await tester.pumpWidget(buildFrame(controller1, showLast: true));
final PageView pageView = tester.widget(find.byType(PageView)); final PageView pageView = tester.widget(find.byType(PageView));
final PageController pageController = pageView.controller; final PageController pageController = pageView.controller;
await tester.tap(find.text('three')); await tester.tap(find.text('three'));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(controller1.index, 2); expect(controller1.index, 2);
expect(pageController.page, 2); expect(pageController.page, 2);
// Change TabController from 3 items to 2. // Change TabController from 3 items to 2.
await tester.pumpWidget(buildFrame(controller2, false)); await tester.pumpWidget(buildFrame(controller2, showLast: false));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(controller2.index, 0); expect(controller2.index, 0);
expect(pageController.page, 0); expect(pageController.page, 0);
// Change TabController from 2 items to 3. // Change TabController from 2 items to 3.
await tester.pumpWidget(buildFrame(controller3, true)); await tester.pumpWidget(buildFrame(controller3, showLast: true));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(controller3.index, 0); expect(controller3.index, 0);
expect(pageController.page, 0); expect(pageController.page, 0);
...@@ -4323,6 +4322,71 @@ void main() { ...@@ -4323,6 +4322,71 @@ void main() {
expect(pageController.page, 2); expect(pageController.page, 2);
}); });
testWidgets('Do not crash when the new TabController.index is longer than the old length.', (WidgetTester tester) async {
// This is a regression test for https://github.com/flutter/flutter/issues/97441
Widget buildFrame(TabController controller, {required bool showLast}) {
return boilerplate(
child: Column(
children: <Widget>[
TabBar(
controller: controller,
tabs: <Tab>[
const Tab(text: 'one'),
const Tab(text: 'two'),
if (showLast) const Tab(text: 'three'),
],
),
Flexible(
child: TabBarView(
controller: controller,
children: <Widget>[
const Text('PAGE1'),
const Text('PAGE2'),
if (showLast) const Text('PAGE3'),
],
),
),
],
),
);
}
final TabController controller1 = TabController(
vsync: const TestVSync(),
length: 3,
);
final TabController controller2 = TabController(
vsync: const TestVSync(),
length: 2,
);
await tester.pumpWidget(buildFrame(controller1, showLast: true));
PageView pageView = tester.widget(find.byType(PageView));
PageController pageController = pageView.controller;
await tester.tap(find.text('three'));
await tester.pumpAndSettle();
expect(controller1.index, 2);
expect(pageController.page, 2);
// Change TabController from controller1 to controller2.
await tester.pumpWidget(buildFrame(controller2, showLast: false));
await tester.pumpAndSettle();
pageView = tester.widget(find.byType(PageView));
pageController = pageView.controller;
expect(controller2.index, 0);
expect(pageController.page, 0);
// Change TabController back to 'controller1' whose index is 2.
await tester.pumpWidget(buildFrame(controller1, showLast: true));
await tester.pumpAndSettle();
pageView = tester.widget(find.byType(PageView));
pageController = pageView.controller;
expect(controller1.index, 2);
expect(pageController.page, 2);
});
testWidgets('TabBar InkWell splashFactory and overlayColor', (WidgetTester tester) async { testWidgets('TabBar InkWell splashFactory and overlayColor', (WidgetTester tester) async {
const InteractiveInkFeatureFactory splashFactory = NoSplash.splashFactory; const InteractiveInkFeatureFactory splashFactory = NoSplash.splashFactory;
final MaterialStateProperty<Color?> overlayColor = MaterialStateProperty.resolveWith<Color?>( final MaterialStateProperty<Color?> overlayColor = MaterialStateProperty.resolveWith<Color?>(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment