Skip to content

Commit 0139761

Browse files
authored
Fix TabBar crash with SliverAppBar (flutter#154485)
Fixes flutter#154484 Similar to flutter#104998. Cause with updated at different phases of the same frame.
1 parent cede6ba commit 0139761

File tree

4 files changed

+57
-6
lines changed

4 files changed

+57
-6
lines changed

packages/flutter/lib/src/material/reorderable_list.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ class ReorderableListView extends StatefulWidget {
219219
///
220220
///
221221
/// ** See code in examples/api/lib/material/reorderable_list/reorderable_list_view.build_default_drag_handles.0.dart **
222-
///{@end-tool}
222+
/// {@end-tool}
223223
final bool buildDefaultDragHandles;
224224

225225
/// {@macro flutter.widgets.reorderable_list.padding}

packages/flutter/lib/src/material/tabs.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,9 +1742,11 @@ class _TabBarState extends State<TabBar> {
17421742
wrappedTabs[previousIndex] = _buildStyledTab(wrappedTabs[previousIndex], false, animation, _defaults);
17431743
} else {
17441744
// The user is dragging the TabBarView's PageView left or right.
1745-
final int tabIndex = _currentIndex!;
1746-
final Animation<double> centerAnimation = _DragAnimation(_controller!, tabIndex);
1747-
wrappedTabs[tabIndex] = _buildStyledTab(wrappedTabs[tabIndex], true, centerAnimation, _defaults);
1745+
if (_currentIndex! < widget.tabs.length) {
1746+
final int tabIndex = _currentIndex!;
1747+
final Animation<double> centerAnimation = _DragAnimation(_controller!, tabIndex);
1748+
wrappedTabs[tabIndex] = _buildStyledTab(wrappedTabs[tabIndex], true, centerAnimation, _defaults);
1749+
}
17481750
if (_currentIndex! > 0) {
17491751
final int tabIndex = _currentIndex! - 1;
17501752
final Animation<double> previousAnimation = ReverseAnimation(_DragAnimation(_controller!, tabIndex));

packages/flutter/lib/src/widgets/editable_text.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,10 +1618,10 @@ class EditableText extends StatefulWidget {
16181618
/// {@endtemplate}
16191619
final bool cursorOpacityAnimates;
16201620

1621-
///{@macro flutter.rendering.RenderEditable.cursorOffset}
1621+
/// {@macro flutter.rendering.RenderEditable.cursorOffset}
16221622
final Offset? cursorOffset;
16231623

1624-
///{@macro flutter.rendering.RenderEditable.paintCursorAboveText}
1624+
/// {@macro flutter.rendering.RenderEditable.paintCursorAboveText}
16251625
final bool paintCursorAboveText;
16261626

16271627
/// Controls how tall the selection highlight boxes are computed to be.

packages/flutter/test/material/tabs_test.dart

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5947,6 +5947,55 @@ void main() {
59475947
gesture.removePointer();
59485948
});
59495949

5950+
testWidgets('No crash if TabBar build called before didUpdateWidget with SliverAppBar', (WidgetTester tester) async {
5951+
// Regression test for https://github.com/flutter/flutter/issues/154484.
5952+
final List<String> tabs = <String>[];
5953+
5954+
await tester.pumpWidget(
5955+
MaterialApp(
5956+
home: StatefulBuilder(
5957+
builder: (BuildContext context, StateSetter setState) {
5958+
return DefaultTabController(
5959+
length: tabs.length,
5960+
child: Scaffold(
5961+
body: CustomScrollView(
5962+
slivers: <Widget>[
5963+
SliverAppBar(
5964+
actions: <Widget>[
5965+
TextButton(
5966+
child: const Text('Add Tab'),
5967+
onPressed: () {
5968+
setState(() {
5969+
tabs.add('Tab ${tabs.length + 1}');
5970+
});
5971+
},
5972+
),
5973+
],
5974+
bottom: TabBar(
5975+
tabs: tabs.map((String tab) => Tab(text: tab)).toList(),
5976+
),
5977+
),
5978+
],
5979+
),
5980+
),
5981+
);
5982+
},
5983+
),
5984+
),
5985+
);
5986+
5987+
// Initializes with zero tabs.
5988+
expect(find.text('Tab 1'), findsNothing);
5989+
expect(find.text('Tab 2'), findsNothing);
5990+
5991+
// No crash after tabs added.
5992+
await tester.tap(find.text('Add Tab'));
5993+
await tester.pumpAndSettle();
5994+
expect(find.text('Tab 1'), findsOneWidget);
5995+
expect(find.text('Tab 2'), findsNothing);
5996+
expect(tester.takeException(), isNull);
5997+
});
5998+
59505999
testWidgets('Do not crash if the controller and TabBarView are updated at different phases(build and layout) of the same frame', (WidgetTester tester) async {
59516000
// Regression test for https://github.com/flutter/flutter/issues/104994.
59526001
List<String> tabTextContent = <String>[];

0 commit comments

Comments
 (0)