Fix a Tabs crash when change the TabControllers (#98242)
This commit is contained in:
parent
83a88058d6
commit
2ce43fac7b
@ -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() {
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
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?>(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user