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 {