Modified TabBar.preferredSize to remove hardcoded (#80792)
diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart index 9bf2fa9..6b333b6 100644 --- a/packages/flutter/lib/src/material/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:math' as math; import 'dart:ui' show lerpDouble; import 'package:flutter/foundation.dart'; @@ -57,7 +58,7 @@ /// * [TabBarView], which displays a widget for the currently selected tab. /// * [TabController], which coordinates tab selection between a [TabBar] and a [TabBarView]. /// * <https://material.io/design/components/tabs.html> -class Tab extends StatelessWidget { +class Tab extends StatelessWidget implements PreferredSizeWidget{ /// Creates a material design [TabBar] tab. /// /// At least one of [text], [icon], and [child] must be non-null. The [text] @@ -141,6 +142,14 @@ properties.add(StringProperty('text', text, defaultValue: null)); properties.add(DiagnosticsProperty<Widget>('icon', icon, defaultValue: null)); } + + @override + Size get preferredSize { + if ((text != null || child != null) && icon != null) + return const Size.fromHeight(_kTextAndIconTabHeight); + else + return const Size.fromHeight(_kTabHeight); + } } class _TabStyle extends AnimatedWidget { @@ -891,14 +900,14 @@ /// [AppBar] uses this size to compute its own preferred size. @override Size get preferredSize { + double maxHeight = _kTabHeight; for (final Widget item in tabs) { - if (item is Tab) { - final Tab tab = item; - if ((tab.text != null || tab.child != null) && tab.icon != null) - return Size.fromHeight(_kTextAndIconTabHeight + indicatorWeight); + if (item is PreferredSizeWidget) { + final double itemHeight = item.preferredSize.height; + maxHeight = math.max(itemHeight, maxHeight); } } - return Size.fromHeight(_kTabHeight + indicatorWeight); + return Size.fromHeight(maxHeight + indicatorWeight); } @override
diff --git a/packages/flutter/test/material/tabs_test.dart b/packages/flutter/test/material/tabs_test.dart index 0359790..414d211 100644 --- a/packages/flutter/test/material/tabs_test.dart +++ b/packages/flutter/test/material/tabs_test.dart
@@ -3457,6 +3457,82 @@ expect(controller.index, 1); expect(controller.animation!.value, 1); }); + + testWidgets('Tab preferredSize gives correct value', (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: Material( + child: Row( + children: const <Tab>[ + Tab(icon: Icon(Icons.message)), + Tab(text: 'Two'), + Tab(text: 'Three', icon: Icon(Icons.chat)), + ], + ), + ), + ), + ); + + final Tab firstTab = tester.widget(find.widgetWithIcon(Tab, Icons.message)); + final Tab secondTab = tester.widget(find.widgetWithText(Tab, 'Two')); + final Tab thirdTab = tester.widget(find.widgetWithText(Tab, 'Three')); + + expect(firstTab.preferredSize, const Size.fromHeight(46.0)); + expect(secondTab.preferredSize, const Size.fromHeight(46.0)); + expect(thirdTab.preferredSize, const Size.fromHeight(72.0)); + }); + + testWidgets('TabBar preferredSize gives correct value when there are both icon and text in tabs', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + home: DefaultTabController( + length: 5, + child: Scaffold( + appBar: AppBar( + bottom: const TabBar( + tabs: <Widget>[ + Tab(text: 'car'), + Tab(text: 'transit'), + Tab(text: 'bike'), + Tab(text: 'boat', icon: Icon(Icons.message)), + Tab(text: 'bus'), + ], + ), + title: const Text('Tabs Test'), + ), + ), + ), + )); + + final TabBar tabBar = tester.widget(find.widgetWithText(TabBar, 'car')); + + expect(tabBar.preferredSize, const Size.fromHeight(74.0)); + }); + + testWidgets('TabBar preferredSize gives correct value when there is only icon or text in tabs', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + home: DefaultTabController( + length: 5, + child: Scaffold( + appBar: AppBar( + bottom: const TabBar( + tabs: <Widget>[ + Tab(text: 'car'), + Tab(icon: Icon(Icons.message)), + Tab(text: 'bike'), + Tab(icon: Icon(Icons.chat)), + Tab(text: 'bus'), + ], + ), + title: const Text('Tabs Test'), + ), + ), + ), + )); + + final TabBar tabBar = tester.widget(find.widgetWithText(TabBar, 'car')); + + expect(tabBar.preferredSize, const Size.fromHeight(48.0)); + }); } class KeepAliveInk extends StatefulWidget {