Skip to content

Commit

Permalink
Fix TabController throws build scheduled during frame error (#105442)
Browse files Browse the repository at this point in the history
  • Loading branch information
bleroux committed Jul 11, 2022
1 parent 40fc5e8 commit 082ad11
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 6 deletions.
15 changes: 9 additions & 6 deletions packages/flutter/lib/src/material/tabs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1495,15 +1495,13 @@ class _TabBarViewState extends State<TabBarView> {
}

final Duration duration = _controller!.animationDuration;

if (duration == Duration.zero) {
_pageController.jumpToPage(_currentIndex!);
return Future<void>.value();
}

final int previousIndex = _controller!.previousIndex;

if ((_currentIndex! - previousIndex).abs() == 1) {
if (duration == Duration.zero) {
_pageController.jumpToPage(_currentIndex!);
return Future<void>.value();
}
_warpUnderwayCount += 1;
await _pageController.animateToPage(_currentIndex!, duration: duration, curve: Curves.ease);
_warpUnderwayCount -= 1;
Expand All @@ -1525,6 +1523,11 @@ class _TabBarViewState extends State<TabBarView> {
});
_pageController.jumpToPage(initialPage);

if (duration == Duration.zero) {
_pageController.jumpToPage(_currentIndex!);
return Future<void>.value();
}

await _pageController.animateToPage(_currentIndex!, duration: duration, curve: Curves.ease);
if (!mounted) {
return Future<void>.value();
Expand Down
45 changes: 45 additions & 0 deletions packages/flutter/test/material/tabs_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,51 @@ void main() {
expect(controller.indexIsChanging, false);
});

testWidgets('TabBar should not throw when animation is disabled in controller', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/102600
final List<String> tabs = <String>['A'];

Widget buildWithTabBarView() {
return boilerplate(
child: DefaultTabController(
animationDuration: Duration.zero,
length: tabs.length,
child: Column(
children: <Widget>[
TabBar(
tabs: tabs.map<Widget>((String tab) => Tab(text: tab)).toList(),
isScrollable: true,
),
Flexible(
child: TabBarView(
children: List<Widget>.generate(
tabs.length,
(int index) => Text('Tab $index'),
),
),
),
],
),
),
);
}

await tester.pumpWidget(buildWithTabBarView());
TabController controller = DefaultTabController.of(tester.element(find.text('A')))!;
expect(controller.index, 0);

tabs.add('B');
await tester.pumpWidget(buildWithTabBarView());
tabs.add('C');
await tester.pumpWidget(buildWithTabBarView());
await tester.tap(find.text('C'));
await tester.pumpAndSettle();
controller = DefaultTabController.of(tester.element(find.text('A')))!;
expect(controller.index, 2);

expect(tester.takeException(), isNull);
});

testWidgets('TabBarView skips animation when disabled in controller', (WidgetTester tester) async {
final List<String> tabs = <String>['A', 'B', 'C'];
final TabController tabController = TabController(
Expand Down

0 comments on commit 082ad11

Please sign in to comment.