diff --git a/dev/tools/gen_defaults/generated/used_tokens.csv b/dev/tools/gen_defaults/generated/used_tokens.csv index 0054b8cfab..6fb5c5ac68 100644 --- a/dev/tools/gen_defaults/generated/used_tokens.csv +++ b/dev/tools/gen_defaults/generated/used_tokens.csv @@ -529,7 +529,6 @@ md.comp.primary-navigation-tab.active.hover.state-layer.opacity, md.comp.primary-navigation-tab.active.pressed.state-layer.color, md.comp.primary-navigation-tab.active.pressed.state-layer.opacity, md.comp.primary-navigation-tab.divider.color, -md.comp.primary-navigation-tab.divider.height, md.comp.primary-navigation-tab.inactive.focus.state-layer.color, md.comp.primary-navigation-tab.inactive.focus.state-layer.opacity, md.comp.primary-navigation-tab.inactive.hover.state-layer.color, @@ -589,7 +588,6 @@ md.comp.search-view.header.supporting-text.color, md.comp.search-view.header.supporting-text.text-style, md.comp.secondary-navigation-tab.active.label-text.color, md.comp.secondary-navigation-tab.divider.color, -md.comp.secondary-navigation-tab.divider.height, md.comp.secondary-navigation-tab.focus.state-layer.color, md.comp.secondary-navigation-tab.focus.state-layer.opacity, md.comp.secondary-navigation-tab.hover.state-layer.color, diff --git a/dev/tools/gen_defaults/lib/tabs_template.dart b/dev/tools/gen_defaults/lib/tabs_template.dart index f520f617b2..f6388a8745 100644 --- a/dev/tools/gen_defaults/lib/tabs_template.dart +++ b/dev/tools/gen_defaults/lib/tabs_template.dart @@ -24,9 +24,6 @@ class _${blockName}PrimaryDefaultsM3 extends TabBarTheme { @override Color? get dividerColor => ${componentColor("md.comp.primary-navigation-tab.divider")}; - @override - double? get dividerHeight => ${getToken('md.comp.primary-navigation-tab.divider.height')}; - @override Color? get indicatorColor => ${componentColor("md.comp.primary-navigation-tab.active-indicator")}; @@ -74,7 +71,7 @@ class _${blockName}PrimaryDefaultsM3 extends TabBarTheme { InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory; @override - TabAlignment? get tabAlignment => isScrollable ? TabAlignment.startOffset : TabAlignment.fill; + TabAlignment? get tabAlignment => isScrollable ? TabAlignment.start : TabAlignment.fill; static double indicatorWeight = ${getToken('md.comp.primary-navigation-tab.active-indicator.height')}; } @@ -91,9 +88,6 @@ class _${blockName}SecondaryDefaultsM3 extends TabBarTheme { @override Color? get dividerColor => ${componentColor("md.comp.secondary-navigation-tab.divider")}; - @override - double? get dividerHeight => ${getToken('md.comp.secondary-navigation-tab.divider.height')}; - @override Color? get indicatorColor => ${componentColor("md.comp.primary-navigation-tab.active-indicator")}; @@ -141,7 +135,7 @@ class _${blockName}SecondaryDefaultsM3 extends TabBarTheme { InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory; @override - TabAlignment? get tabAlignment => isScrollable ? TabAlignment.startOffset : TabAlignment.fill; + TabAlignment? get tabAlignment => isScrollable ? TabAlignment.start : TabAlignment.fill; } '''; diff --git a/packages/flutter/lib/src/material/tab_bar_theme.dart b/packages/flutter/lib/src/material/tab_bar_theme.dart index e65e8b3c4d..87c43d7acf 100644 --- a/packages/flutter/lib/src/material/tab_bar_theme.dart +++ b/packages/flutter/lib/src/material/tab_bar_theme.dart @@ -32,7 +32,6 @@ class TabBarTheme with Diagnosticable { this.indicatorColor, this.indicatorSize, this.dividerColor, - this.dividerHeight, this.labelColor, this.labelPadding, this.labelStyle, @@ -56,9 +55,6 @@ class TabBarTheme with Diagnosticable { /// Overrides the default value for [TabBar.dividerColor]. final Color? dividerColor; - /// Overrides the default value for [TabBar.dividerHeight]. - final double? dividerHeight; - /// Overrides the default value for [TabBar.labelColor]. /// /// If [labelColor] is a [MaterialStateColor], then the effective color will @@ -105,7 +101,6 @@ class TabBarTheme with Diagnosticable { Color? indicatorColor, TabBarIndicatorSize? indicatorSize, Color? dividerColor, - double? dividerHeight, Color? labelColor, EdgeInsetsGeometry? labelPadding, TextStyle? labelStyle, @@ -121,7 +116,6 @@ class TabBarTheme with Diagnosticable { indicatorColor: indicatorColor ?? this.indicatorColor, indicatorSize: indicatorSize ?? this.indicatorSize, dividerColor: dividerColor ?? this.dividerColor, - dividerHeight: dividerHeight ?? this.dividerHeight, labelColor: labelColor ?? this.labelColor, labelPadding: labelPadding ?? this.labelPadding, labelStyle: labelStyle ?? this.labelStyle, @@ -153,7 +147,6 @@ class TabBarTheme with Diagnosticable { indicatorColor: Color.lerp(a.indicatorColor, b.indicatorColor, t), indicatorSize: t < 0.5 ? a.indicatorSize : b.indicatorSize, dividerColor: Color.lerp(a.dividerColor, b.dividerColor, t), - dividerHeight: t < 0.5 ? a.dividerHeight : b.dividerHeight, labelColor: Color.lerp(a.labelColor, b.labelColor, t), labelPadding: EdgeInsetsGeometry.lerp(a.labelPadding, b.labelPadding, t), labelStyle: TextStyle.lerp(a.labelStyle, b.labelStyle, t), @@ -172,7 +165,6 @@ class TabBarTheme with Diagnosticable { indicatorColor, indicatorSize, dividerColor, - dividerHeight, labelColor, labelPadding, labelStyle, @@ -197,7 +189,6 @@ class TabBarTheme with Diagnosticable { && other.indicatorColor == indicatorColor && other.indicatorSize == indicatorSize && other.dividerColor == dividerColor - && other.dividerHeight == dividerHeight && other.labelColor == labelColor && other.labelPadding == labelPadding && other.labelStyle == labelStyle diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart index 29f53dcb05..756e61c7f2 100644 --- a/packages/flutter/lib/src/material/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart @@ -397,8 +397,6 @@ class _IndicatorPainter extends CustomPainter { required this.indicatorPadding, required this.labelPaddings, this.dividerColor, - this.dividerHeight, - required this.width, }) : super(repaint: controller.animation) { if (old != null) { saveTabOffsets(old._currentTabOffsets, old._currentTextDirection); @@ -410,10 +408,8 @@ class _IndicatorPainter extends CustomPainter { final TabBarIndicatorSize? indicatorSize; final EdgeInsetsGeometry indicatorPadding; final List tabKeys; - final List labelPaddings; final Color? dividerColor; - final double? dividerHeight; - final double width; + final List labelPaddings; // _currentTabOffsets and _currentTextDirection are set each time TabBar // layout is completed. These values can be null when TabBar contains no @@ -506,10 +502,8 @@ class _IndicatorPainter extends CustomPainter { textDirection: _currentTextDirection, ); if (dividerColor != null) { - final Paint dividerPaint = Paint()..color = dividerColor!..strokeWidth = dividerHeight!; - final Offset dividerP1 = Offset(-width, size.height - (dividerPaint.strokeWidth / 2)); - final Offset dividerP2 = Offset(width, size.height - (dividerPaint.strokeWidth / 2)); - canvas.drawLine(dividerP1, dividerP2, dividerPaint); + final Paint dividerPaint = Paint()..color = dividerColor!..strokeWidth = 1; + canvas.drawLine(Offset(0, size.height), Offset(size.width, size.height), dividerPaint); } _painter!.paint(canvas, _currentRect!.topLeft, configuration); } @@ -724,7 +718,6 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget { this.indicator, this.indicatorSize, this.dividerColor, - this.dividerHeight, this.labelColor, this.labelStyle, this.labelPadding, @@ -775,7 +768,6 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget { this.indicator, this.indicatorSize, this.dividerColor, - this.dividerHeight, this.labelColor, this.labelStyle, this.labelPadding, @@ -903,13 +895,6 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget { /// [ColorScheme.surfaceVariant] will be used, otherwise divider will not be drawn. final Color? dividerColor; - /// The height of the divider. - /// - /// If null and [ThemeData.useMaterial3] is true, [TabBarTheme.dividerHeight] is used. - /// If that is also null and [ThemeData.useMaterial3] is true, 1.0 will be used. - /// Otherwise divider will not be drawn. - final double? dividerHeight; - /// The color of selected tab labels. /// /// If null, then [TabBarTheme.labelColor] is used. If that is also null and @@ -1169,8 +1154,8 @@ class _TabBarState extends State { TabBarTheme get _defaults { if (Theme.of(context).useMaterial3) { return widget._isPrimary - ? _TabsPrimaryDefaultsM3(context, widget.isScrollable) - : _TabsSecondaryDefaultsM3(context, widget.isScrollable); + ? _TabsPrimaryDefaultsM3(context, widget.isScrollable) + : _TabsSecondaryDefaultsM3(context, widget.isScrollable); } else { return _TabsDefaultsM2(context, widget.isScrollable); } @@ -1284,10 +1269,8 @@ class _TabBarState extends State { indicatorPadding: widget.indicatorPadding, tabKeys: _tabKeys, old: _indicatorPainter, - labelPaddings: _labelPaddings, dividerColor: theme.useMaterial3 ? widget.dividerColor ?? tabBarTheme.dividerColor ?? _defaults.dividerColor : null, - dividerHeight: theme.useMaterial3 ? widget.dividerHeight ?? tabBarTheme.dividerHeight ?? _defaults.dividerHeight : null, - width: MediaQuery.sizeOf(context).width, + labelPaddings: _labelPaddings, ); } @@ -1492,7 +1475,6 @@ class _TabBarState extends State { Widget build(BuildContext context) { assert(debugCheckHasMaterialLocalizations(context)); assert(_debugScheduleCheckHasValidTabsCount()); - final ThemeData theme = Theme.of(context); final TabBarTheme tabBarTheme = TabBarTheme.of(context); final TabAlignment effectiveTabAlignment = widget.tabAlignment ?? tabBarTheme.tabAlignment ?? _defaults.tabAlignment!; assert(_debugTabAlignmentIsValid(effectiveTabAlignment)); @@ -1645,17 +1627,6 @@ class _TabBarState extends State { child: tabBar, ), ); - if (theme.useMaterial3) { - final AlignmentGeometry effectiveAlignment = switch (effectiveTabAlignment) { - TabAlignment.center => Alignment.center, - TabAlignment.start || TabAlignment.startOffset || TabAlignment.fill => AlignmentDirectional.centerStart, - }; - tabBar = Align( - heightFactor: 1.0, - alignment: effectiveAlignment, - child: tabBar, - ); - } } else if (widget.padding != null) { tabBar = Padding( padding: widget.padding!, @@ -2206,9 +2177,6 @@ class _TabsPrimaryDefaultsM3 extends TabBarTheme { @override Color? get dividerColor => _colors.surfaceVariant; - @override - double? get dividerHeight => 1.0; - @override Color? get indicatorColor => _colors.primary; @@ -2256,7 +2224,7 @@ class _TabsPrimaryDefaultsM3 extends TabBarTheme { InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory; @override - TabAlignment? get tabAlignment => isScrollable ? TabAlignment.startOffset : TabAlignment.fill; + TabAlignment? get tabAlignment => isScrollable ? TabAlignment.start : TabAlignment.fill; static double indicatorWeight = 3.0; } @@ -2273,9 +2241,6 @@ class _TabsSecondaryDefaultsM3 extends TabBarTheme { @override Color? get dividerColor => _colors.surfaceVariant; - @override - double? get dividerHeight => 1.0; - @override Color? get indicatorColor => _colors.primary; @@ -2323,7 +2288,7 @@ class _TabsSecondaryDefaultsM3 extends TabBarTheme { InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory; @override - TabAlignment? get tabAlignment => isScrollable ? TabAlignment.startOffset : TabAlignment.fill; + TabAlignment? get tabAlignment => isScrollable ? TabAlignment.start : TabAlignment.fill; } // END GENERATED TOKEN PROPERTIES - Tabs diff --git a/packages/flutter/test/material/tab_bar_theme_test.dart b/packages/flutter/test/material/tab_bar_theme_test.dart index 4de788b1e1..4b8c5a9243 100644 --- a/packages/flutter/test/material/tab_bar_theme_test.dart +++ b/packages/flutter/test/material/tab_bar_theme_test.dart @@ -88,7 +88,6 @@ void main() { expect(const TabBarTheme().indicatorColor, null); expect(const TabBarTheme().indicatorSize, null); expect(const TabBarTheme().dividerColor, null); - expect(const TabBarTheme().dividerHeight, null); expect(const TabBarTheme().labelColor, null); expect(const TabBarTheme().labelPadding, null); expect(const TabBarTheme().labelStyle, null); @@ -126,32 +125,27 @@ void main() { final Rect tabBar = tester.getRect(find.byType(TabBar)); final Rect tabOneRect = tester.getRect(find.byKey(_sizedTabs[0].key!)); final Rect tabTwoRect = tester.getRect(find.byKey(_sizedTabs[1].key!)); - const double tabStartOffset = 52.0; // Verify tabOne coordinates. - expect(tabOneRect.left, equals(kTabLabelPadding.left + tabStartOffset)); + expect(tabOneRect.left, equals(kTabLabelPadding.left)); expect(tabOneRect.top, equals(kTabLabelPadding.top)); expect(tabOneRect.bottom, equals(tabBar.bottom - kTabLabelPadding.bottom - indicatorWeight)); // Verify tabTwo coordinates. - final double tabTwoRight = tabStartOffset + kTabLabelPadding.horizontal + tabOneRect.width - + kTabLabelPadding.left + tabTwoRect.width; - expect(tabTwoRect.right, tabTwoRight); + expect(tabTwoRect.right, equals(tabBar.width - kTabLabelPadding.right)); expect(tabTwoRect.top, equals(kTabLabelPadding.top)); expect(tabTwoRect.bottom, equals(tabBar.bottom - kTabLabelPadding.bottom - indicatorWeight)); - // Verify tabOne and tabTwo are separated by right padding of tabOne and left padding of tabTwo. + // Verify tabOne and tabTwo is separated by right padding of tabOne and left padding of tabTwo. expect(tabOneRect.right, equals(tabTwoRect.left - kTabLabelPadding.left - kTabLabelPadding.right)); - // Test default indicator & divider color. + // Test default indicator color and divider color. final RenderBox tabBarBox = tester.firstRenderObject(find.byType(TabBar)); expect( tabBarBox, paints - ..line( - color: theme.colorScheme.surfaceVariant, - strokeWidth: 1.0, - ) + ..line(color: theme.colorScheme.surfaceVariant) + // Indicator is a rrect in the primary tab bar. ..rrect(color: theme.colorScheme.primary), ); }); @@ -182,34 +176,29 @@ void main() { final Rect tabBar = tester.getRect(find.byType(TabBar)); final Rect tabOneRect = tester.getRect(find.byKey(_sizedTabs[0].key!)); final Rect tabTwoRect = tester.getRect(find.byKey(_sizedTabs[1].key!)); - const double tabStartOffset = 52.0; // Verify tabOne coordinates. - expect(tabOneRect.left, equals(kTabLabelPadding.left + tabStartOffset)); + expect(tabOneRect.left, equals(kTabLabelPadding.left)); expect(tabOneRect.top, equals(kTabLabelPadding.top)); expect(tabOneRect.bottom, equals(tabBar.bottom - kTabLabelPadding.bottom - indicatorWeight)); // Verify tabTwo coordinates. - final double tabTwoRight = tabStartOffset + kTabLabelPadding.horizontal + tabOneRect.width - + kTabLabelPadding.left + tabTwoRect.width; - expect(tabTwoRect.right, tabTwoRight); + expect(tabTwoRect.right, equals(tabBar.width - kTabLabelPadding.right)); expect(tabTwoRect.top, equals(kTabLabelPadding.top)); expect(tabTwoRect.bottom, equals(tabBar.bottom - kTabLabelPadding.bottom - indicatorWeight)); - // Verify tabOne and tabTwo are separated by right padding of tabOne and left padding of tabTwo. + // Verify tabOne and tabTwo is separated by right padding of tabOne and left padding of tabTwo. expect(tabOneRect.right, equals(tabTwoRect.left - kTabLabelPadding.left - kTabLabelPadding.right)); - // Test default indicator & divider color. + // Test default indicator color and divider color. final RenderBox tabBarBox = tester.firstRenderObject(find.byType(TabBar)); expect( tabBarBox, paints - ..line( - color: theme.colorScheme.surfaceVariant, - strokeWidth: 1.0, - ) + ..line(color: theme.colorScheme.surfaceVariant) + // Indicator is a line in the secondary tab bar. ..line(color: theme.colorScheme.primary), - ); + ); }); testWidgets('Tab bar theme overrides label color (selected)', (WidgetTester tester) async { @@ -390,7 +379,7 @@ void main() { expect(iconRenderObject.text.style!.color, equals(unselectedLabelColor)); }); - testWidgets('Tab bar default tab indicator size (primary)', (WidgetTester tester) async { + testWidgets('Tab bar default tab indicator size', (WidgetTester tester) async { await tester.pumpWidget(buildTabBar(useMaterial3: true, isScrollable: true)); await expectLater( @@ -399,12 +388,12 @@ void main() { ); }); - testWidgets('Tab bar default tab indicator size (secondary)', (WidgetTester tester) async { + testWidgets('Tab bar default tab indicator size', (WidgetTester tester) async { await tester.pumpWidget(buildTabBar(useMaterial3: true, isScrollable: true)); await expectLater( find.byKey(_painterKey), - matchesGoldenFile('tab_bar_secondary.default.tab_indicator_size.png'), + matchesGoldenFile('tab_bar.default.tab_indicator_size.png'), ); }); @@ -558,12 +547,11 @@ void main() { expect( tabBarBox, paints - // Divider. + // Divider ..line( color: theme.colorScheme.surfaceVariant, - strokeWidth: 1.0, ) - // Tab indicator. + // Tab indicator ..line( color: theme.colorScheme.primary, strokeWidth: indicatorWeight, @@ -611,10 +599,9 @@ void main() { expect( tabBarBox, paints - // Divider. + // Divider ..line( color: theme.colorScheme.surfaceVariant, - strokeWidth: 1.0, ) // Tab indicator ..line( @@ -626,202 +613,6 @@ void main() { ); }); - testWidgets('TabBar divider can use TabBarTheme.dividerColor & TabBarTheme.dividerHeight', (WidgetTester tester) async { - const Color dividerColor = Color(0xff00ff00); - const double dividerHeight = 10.0; - - await tester.pumpWidget( - MaterialApp( - theme: ThemeData( - tabBarTheme: const TabBarTheme( - dividerColor: dividerColor, - dividerHeight: dividerHeight, - ), - useMaterial3: true, - ), - home: Scaffold( - appBar: AppBar( - bottom: TabBar( - controller: TabController(length: 3, vsync: const TestVSync()), - tabs: const [ - Tab(text: 'Tab 1'), - Tab(text: 'Tab 2'), - Tab(text: 'Tab 3'), - ], - ), - ), - ), - ), - ); - - final RenderBox tabBarBox = tester.firstRenderObject(find.byType(TabBar)); - // Test divider color. - expect(tabBarBox, paints..line(color: dividerColor, strokeWidth: dividerHeight)); - }); - - testWidgets('dividerColor & dividerHeight overrides TabBarTheme.dividerColor', (WidgetTester tester) async { - const Color dividerColor = Color(0xff0000ff); - const double dividerHeight = 8.0; - - await tester.pumpWidget( - MaterialApp( - theme: ThemeData( - useMaterial3: true, - tabBarTheme: const TabBarTheme( - dividerColor: Colors.pink, - dividerHeight: 5.0, - ), - ), - home: Scaffold( - appBar: AppBar( - bottom: TabBar( - dividerColor: dividerColor, - dividerHeight: dividerHeight, - controller: TabController(length: 3, vsync: const TestVSync()), - tabs: const [ - Tab(text: 'Tab 1'), - Tab(text: 'Tab 2'), - Tab(text: 'Tab 3'), - ], - ), - ), - ), - ), - ); - - final RenderBox tabBarBox = tester.firstRenderObject(find.byType(TabBar)); - // Test divider color. - expect(tabBarBox, paints..line(color: dividerColor, strokeWidth: dividerHeight)); - }); - - testWidgets('TabBar respects TabBarTheme.tabAlignment', (WidgetTester tester) async { - // Test non-scrollable tab bar. - await tester.pumpWidget( - MaterialApp( - theme: ThemeData( - tabBarTheme: const TabBarTheme(tabAlignment: TabAlignment.center), - useMaterial3: true, - ), - home: Scaffold( - appBar: AppBar( - bottom: TabBar( - controller: TabController(length: 2, vsync: const TestVSync()), - tabs: const [ - Tab(text: 'Tab 1'), - Tab(text: 'Tab 3'), - ], - ), - ), - ), - ), - ); - - const double availableWidth = 800.0; - Rect tabOneRect = tester.getRect(find.byType(Tab).first); - Rect tabTwoRect = tester.getRect(find.byType(Tab).last); - - double tabOneLeft = (availableWidth / 2) - tabOneRect.width - kTabLabelPadding.left; - expect(tabOneRect.left, equals(tabOneLeft)); - double tabTwoRight = (availableWidth / 2) + tabTwoRect.width + kTabLabelPadding.right; - expect(tabTwoRect.right, equals(tabTwoRight)); - - // Test scrollable tab bar. - await tester.pumpWidget( - MaterialApp( - theme: ThemeData( - tabBarTheme: const TabBarTheme(tabAlignment: TabAlignment.start), - useMaterial3: true, - ), - home: Scaffold( - appBar: AppBar( - bottom: TabBar( - isScrollable: true, - controller: TabController(length: 2, vsync: const TestVSync()), - tabs: const [ - Tab(text: 'Tab 1'), - Tab(text: 'Tab 3'), - ], - ), - ), - ), - ), - ); - await tester.pumpAndSettle(); - - tabOneRect = tester.getRect(find.byType(Tab).first); - tabTwoRect = tester.getRect(find.byType(Tab).last); - - tabOneLeft = kTabLabelPadding.left; - expect(tabOneRect.left, equals(tabOneLeft)); - tabTwoRight = kTabLabelPadding.horizontal + tabOneRect.width + kTabLabelPadding.left + tabTwoRect.width; - expect(tabTwoRect.right, equals(tabTwoRight)); - }); - - testWidgets('TabBar.tabAlignment overrides TabBarTheme.tabAlignment', (WidgetTester tester) async { - /// Test non-scrollable tab bar. - await tester.pumpWidget( - MaterialApp( - theme: ThemeData( - tabBarTheme: const TabBarTheme(tabAlignment: TabAlignment.fill), - useMaterial3: true, - ), - home: Scaffold( - appBar: AppBar( - bottom: TabBar( - tabAlignment: TabAlignment.center, - controller: TabController(length: 2, vsync: const TestVSync()), - tabs: const [ - Tab(text: 'Tab 1'), - Tab(text: 'Tab 3'), - ], - ), - ), - ), - ), - ); - - const double availableWidth = 800.0; - Rect tabOneRect = tester.getRect(find.byType(Tab).first); - Rect tabTwoRect = tester.getRect(find.byType(Tab).last); - - double tabOneLeft = (availableWidth / 2) - tabOneRect.width - kTabLabelPadding.left; - expect(tabOneRect.left, equals(tabOneLeft)); - double tabTwoRight = (availableWidth / 2) + tabTwoRect.width + kTabLabelPadding.right; - expect(tabTwoRect.right, equals(tabTwoRight)); - - /// Test scrollable tab bar. - await tester.pumpWidget( - MaterialApp( - theme: ThemeData( - tabBarTheme: const TabBarTheme(tabAlignment: TabAlignment.center), - useMaterial3: true, - ), - home: Scaffold( - appBar: AppBar( - bottom: TabBar( - isScrollable: true, - tabAlignment: TabAlignment.start, - controller: TabController(length: 2, vsync: const TestVSync()), - tabs: const [ - Tab(text: 'Tab 1'), - Tab(text: 'Tab 3'), - ], - ), - ), - ), - ), - ); - await tester.pumpAndSettle(); - - tabOneRect = tester.getRect(find.byType(Tab).first); - tabTwoRect = tester.getRect(find.byType(Tab).last); - - tabOneLeft = kTabLabelPadding.left; - expect(tabOneRect.left, equals(tabOneLeft)); - tabTwoRight = kTabLabelPadding.horizontal + tabOneRect.width + kTabLabelPadding.left + tabTwoRect.width; - expect(tabTwoRect.right, equals(tabTwoRight)); - }); - group('Material 2', () { // These tests are only relevant for Material 2. Once Material 2 // support is deprecated and the APIs are removed, these tests @@ -899,7 +690,7 @@ void main() { expect(tabTwoRect.top, equals(kTabLabelPadding.top)); expect(tabTwoRect.bottom, equals(tabBar.bottom - kTabLabelPadding.bottom - indicatorWeight)); - // Verify tabOne and tabTwo are separated by right padding of tabOne and left padding of tabTwo. + // Verify tabOne and tabTwo is separated by right padding of tabOne and left padding of tabTwo. expect(tabOneRect.right, equals(tabTwoRect.left - kTabLabelPadding.left - kTabLabelPadding.right)); // Test default indicator color. @@ -1013,68 +804,5 @@ void main() { ), ); }); - - testWidgets('TabBar respects TabBarTheme.tabAlignment', (WidgetTester tester) async { - // Test non-scrollable tab bar. - await tester.pumpWidget( - MaterialApp( - theme: ThemeData( - tabBarTheme: const TabBarTheme(tabAlignment: TabAlignment.center), - useMaterial3: false, - ), - home: Scaffold( - appBar: AppBar( - bottom: TabBar( - controller: TabController(length: 2, vsync: const TestVSync()), - tabs: const [ - Tab(text: 'Tab 1'), - Tab(text: 'Tab 3'), - ], - ), - ), - ), - ), - ); - - final Rect tabOneRect = tester.getRect(find.byType(Tab).first); - final Rect tabTwoRect = tester.getRect(find.byType(Tab).last); - - final double tabOneLeft = (800 / 2) - tabOneRect.width - kTabLabelPadding.left; - expect(tabOneRect.left, equals(tabOneLeft)); - final double tabTwoRight = (800 / 2) + tabTwoRect.width + kTabLabelPadding.right; - expect(tabTwoRect.right, equals(tabTwoRight)); - }); - - testWidgets('TabBar.tabAlignment overrides TabBarTheme.tabAlignment', (WidgetTester tester) async { - // Test non-scrollable tab bar. - await tester.pumpWidget( - MaterialApp( - theme: ThemeData( - tabBarTheme: const TabBarTheme(tabAlignment: TabAlignment.fill), - useMaterial3: false, - ), - home: Scaffold( - appBar: AppBar( - bottom: TabBar( - tabAlignment: TabAlignment.center, - controller: TabController(length: 2, vsync: const TestVSync()), - tabs: const [ - Tab(text: 'Tab 1'), - Tab(text: 'Tab 3'), - ], - ), - ), - ), - ), - ); - - final Rect tabOneRect = tester.getRect(find.byType(Tab).first); - final Rect tabTwoRect = tester.getRect(find.byType(Tab).last); - - final double tabOneLeft = (800 / 2) - tabOneRect.width - kTabLabelPadding.left; - expect(tabOneRect.left, equals(tabOneLeft)); - final double tabTwoRight = (800 / 2) + tabTwoRect.width + kTabLabelPadding.right; - expect(tabTwoRect.right, equals(tabTwoRight)); - }); }); } diff --git a/packages/flutter/test/material/tabs_test.dart b/packages/flutter/test/material/tabs_test.dart index d6f977155d..c2194170fe 100644 --- a/packages/flutter/test/material/tabs_test.dart +++ b/packages/flutter/test/material/tabs_test.dart @@ -5951,12 +5951,11 @@ void main() { testWidgets('Default TabAlignment', (WidgetTester tester) async { final ThemeData theme = ThemeData(useMaterial3: true); final List tabs = ['A', 'B']; - const double tabStartOffset = 52.0; // Test default TabAlignment when isScrollable is false. await tester.pumpWidget(MaterialApp( theme: theme, - home: buildFrame(tabs: tabs, value: 'B', useMaterial3: theme.useMaterial3), + home: buildFrame(tabs: tabs, value: 'B'), )); final Rect tabBar = tester.getRect(find.byType(TabBar)); @@ -5972,12 +5971,7 @@ void main() { // Test default TabAlignment when isScrollable is true. await tester.pumpWidget(MaterialApp( theme: theme, - home: buildFrame( - tabs: tabs, - value: 'B', - isScrollable: true, - useMaterial3: theme.useMaterial3, - ), + home: buildFrame(tabs: tabs, value: 'B', isScrollable: true), )); tabOneRect = tester.getRect(find.byType(Tab).first); @@ -5985,8 +5979,8 @@ void main() { // Tabs should be aligned to the start of the TabBar. tabOneLeft = kTabLabelPadding.left; - expect(tabOneRect.left, equals(tabOneLeft + tabStartOffset)); - tabTwoRight = kTabLabelPadding.horizontal + tabStartOffset + tabOneRect.width + kTabLabelPadding.left + tabTwoRect.width; + expect(tabOneRect.left, equals(tabOneLeft)); + tabTwoRight = kTabLabelPadding.horizontal + tabOneRect.width + kTabLabelPadding.left + tabTwoRect.width; expect(tabTwoRect.right, equals(tabTwoRight)); }); @@ -6048,220 +6042,6 @@ void main() { expect(tester.takeException(), isAssertionError); }); - testWidgets('TabAlignment updates tabs alignment (non-scrollable TabBar)', (WidgetTester tester) async { - final ThemeData theme = ThemeData(useMaterial3: true); - final List tabs = ['A', 'B']; - - // Test TabAlignment.fill (default) when isScrollable is false. - await tester.pumpWidget(MaterialApp( - theme: theme, - home: buildFrame(tabs: tabs, value: 'B'), - )); - - const double availableWidth = 800.0; - Rect tabOneRect = tester.getRect(find.byType(Tab).first); - Rect tabTwoRect = tester.getRect(find.byType(Tab).last); - - // By defaults tabs should fill the width of the TabBar. - double tabOneLeft = ((availableWidth / 2) - tabOneRect.width) / 2; - expect(tabOneRect.left, equals(tabOneLeft)); - double tabTwoRight = availableWidth - ((availableWidth / 2) - tabTwoRect.width) / 2; - expect(tabTwoRect.right, equals(tabTwoRight)); - - // Test TabAlignment.center when isScrollable is false. - await tester.pumpWidget(MaterialApp( - theme: theme, - home: buildFrame(tabs: tabs, value: 'B', tabAlignment: TabAlignment.center), - ), - ); - await tester.pumpAndSettle(); - - tabOneRect = tester.getRect(find.byType(Tab).first); - tabTwoRect = tester.getRect(find.byType(Tab).last); - - // Tabs should not fill the width of the TabBar. - tabOneLeft = kTabLabelPadding.left; - expect(tabOneRect.left, equals(tabOneLeft)); - tabTwoRight = kTabLabelPadding.horizontal + tabOneRect.width + kTabLabelPadding.left + tabTwoRect.width; - expect(tabTwoRect.right, equals(tabTwoRight)); - }); - - testWidgets('TabAlignment updates tabs alignment (scrollable TabBar)', (WidgetTester tester) async { - final ThemeData theme = ThemeData(useMaterial3: true); - final List tabs = ['A', 'B']; - const double tabStartOffset = 52.0; - - // Test TabAlignment.startOffset (default) when isScrollable is true. - await tester.pumpWidget(MaterialApp( - theme: theme, - home: buildFrame( - tabs: tabs, - value: 'B', - isScrollable: true, - useMaterial3: theme.useMaterial3, - ), - )); - - final Rect tabBar = tester.getRect(find.byType(TabBar)); - Rect tabOneRect = tester.getRect(find.byType(Tab).first); - Rect tabTwoRect = tester.getRect(find.byType(Tab).last); - - // By default tabs should be aligned to the start of the TabBar with - // an horizontal offset of 52.0 pixels. - double tabOneLeft = kTabLabelPadding.left + tabStartOffset; - expect(tabOneRect.left, equals(tabOneLeft)); - double tabTwoRight = tabStartOffset + kTabLabelPadding.horizontal + tabOneRect.width - + kTabLabelPadding.left + tabTwoRect.width; - expect(tabTwoRect.right, equals(tabTwoRight)); - - // Test TabAlignment.start when isScrollable is true. - await tester.pumpWidget(MaterialApp( - theme: theme, - home: buildFrame( - tabs: tabs, - value: 'B', - isScrollable: true, - tabAlignment: TabAlignment.start, - useMaterial3: theme.useMaterial3, - ), - )); - await tester.pumpAndSettle(); - - tabOneRect = tester.getRect(find.byType(Tab).first); - tabTwoRect = tester.getRect(find.byType(Tab).last); - - // Tabs should be aligned to the start of the TabBar. - tabOneLeft = kTabLabelPadding.left; - expect(tabOneRect.left, equals(tabOneLeft)); - tabTwoRight = kTabLabelPadding.horizontal + tabOneRect.width + kTabLabelPadding.left + tabTwoRect.width; - expect(tabTwoRect.right, equals(tabTwoRight)); - - // Test TabAlignment.center when isScrollable is true. - await tester.pumpWidget(MaterialApp( - theme: theme, - home: buildFrame( - tabs: tabs, - value: 'B', - isScrollable: true, - tabAlignment: TabAlignment.center, - useMaterial3: theme.useMaterial3, - ), - )); - await tester.pumpAndSettle(); - - tabOneRect = tester.getRect(find.byType(Tab).first); - tabTwoRect = tester.getRect(find.byType(Tab).last); - - // Tabs should be centered in the TabBar. - tabOneLeft = (tabBar.width / 2) - tabOneRect.width - kTabLabelPadding.right; - expect(tabOneRect.left, equals(tabOneLeft)); - tabTwoRight = (tabBar.width / 2) + tabTwoRect.width + kTabLabelPadding.left; - expect(tabTwoRect.right, equals(tabTwoRight)); - - // Test TabAlignment.startOffset when isScrollable is true. - await tester.pumpWidget(MaterialApp( - theme: theme, - home: buildFrame( - tabs: tabs, - value: 'B', - isScrollable: true, - tabAlignment: TabAlignment.startOffset, - useMaterial3: theme.useMaterial3, - ), - )); - await tester.pumpAndSettle(); - - tabOneRect = tester.getRect(find.byType(Tab).first); - tabTwoRect = tester.getRect(find.byType(Tab).last); - - // Tabs should be aligned to the start of the TabBar with an - // horizontal offset of 52.0 pixels. - tabOneLeft = kTabLabelPadding.left + tabStartOffset; - expect(tabOneRect.left, equals(tabOneLeft)); - tabTwoRight = tabStartOffset + kTabLabelPadding.horizontal + tabOneRect.width - + kTabLabelPadding.left + tabTwoRect.width; - expect(tabTwoRect.right, equals(tabTwoRight)); - }); - - testWidgets('TabAlignment.start & TabAlignment.startOffset respects TextDirection.rtl', (WidgetTester tester) async { - final ThemeData theme = ThemeData(useMaterial3: true); - final List tabs = ['A', 'B']; - const double tabStartOffset = 52.0; - - // Test TabAlignment.startOffset (default) when isScrollable is true. - await tester.pumpWidget(MaterialApp( - theme: theme, - home: buildFrame( - tabs: tabs, - value: 'B', - isScrollable: true, - textDirection: TextDirection.rtl, - useMaterial3: theme.useMaterial3, - ), - )); - - final Rect tabBar = tester.getRect(find.byType(TabBar)); - Rect tabOneRect = tester.getRect(find.byType(Tab).first); - Rect tabTwoRect = tester.getRect(find.byType(Tab).last); - - // Tabs should be aligned to the start of the TabBar with an - // horizontal offset of 52.0 pixels. - double tabOneRight = tabBar.width - kTabLabelPadding.right - tabStartOffset; - expect(tabOneRect.right, equals(tabOneRight)); - double tabTwoLeft = tabBar.width - tabStartOffset - kTabLabelPadding.horizontal - tabOneRect.width - - kTabLabelPadding.right - tabTwoRect.width; - expect(tabTwoRect.left, equals(tabTwoLeft)); - - // Test TabAlignment.start when isScrollable is true. - await tester.pumpWidget(MaterialApp( - theme: theme, - home: buildFrame( - tabs: tabs, - value: 'B', - isScrollable: true, - tabAlignment: TabAlignment.start, - textDirection: TextDirection.rtl, - useMaterial3: theme.useMaterial3, - ), - )); - await tester.pumpAndSettle(); - - tabOneRect = tester.getRect(find.byType(Tab).first); - tabTwoRect = tester.getRect(find.byType(Tab).last); - - // Tabs should be aligned to the start of the TabBar. - tabOneRight = tabBar.width - kTabLabelPadding.right; - expect(tabOneRect.right, equals(tabOneRight)); - tabTwoLeft = tabBar.width - kTabLabelPadding.horizontal - tabOneRect.width - - kTabLabelPadding.left - tabTwoRect.width; - expect(tabTwoRect.left, equals(tabTwoLeft)); - - // Test TabAlignment.startOffset when isScrollable is true. - await tester.pumpWidget(MaterialApp( - theme: theme, - home: buildFrame( - tabs: tabs, - value: 'B', - isScrollable: true, - tabAlignment: TabAlignment.startOffset, - textDirection: TextDirection.rtl, - useMaterial3: theme.useMaterial3, - ), - )); - await tester.pumpAndSettle(); - - tabOneRect = tester.getRect(find.byType(Tab).first); - tabTwoRect = tester.getRect(find.byType(Tab).last); - - // Tabs should be aligned to the start of the TabBar with an - // horizontal offset of 52.0 pixels. - tabOneRight = tabBar.width - kTabLabelPadding.right - tabStartOffset; - expect(tabOneRect.right, equals(tabOneRight)); - tabTwoLeft = tabBar.width - tabStartOffset - kTabLabelPadding.horizontal - tabOneRect.width - - kTabLabelPadding.right - tabTwoRect.width; - expect(tabTwoRect.left, equals(tabTwoLeft)); - }); - group('Material 2', () { // These tests are only relevant for Material 2. Once Material 2 // support is deprecated and the APIs are removed, these tests @@ -6323,15 +6103,14 @@ void main() { }); testWidgets('Material3 - TabBar inherits the dividerColor of TabBarTheme', (WidgetTester tester) async { - const Color dividerColor = Color(0xff00ff00); - final ThemeData theme = ThemeData( - useMaterial3: true, - tabBarTheme: const TabBarTheme(dividerColor: dividerColor), - ); + const Color dividerColor = Colors.yellow; await tester.pumpWidget( MaterialApp( - theme: theme, + theme: ThemeData( + useMaterial3: true, + tabBarTheme: const TabBarTheme(dividerColor: dividerColor), + ), home: Scaffold( appBar: AppBar( bottom: TabBar( @@ -6347,9 +6126,10 @@ void main() { ), ); - final RenderBox tabBarBox = tester.firstRenderObject(find.byType(TabBar)); - // Test divider color. - expect(tabBarBox, paints..line(color: dividerColor)); + // Test painter's divider color. + final CustomPaint paint = tester.widget(find.byType(CustomPaint).last); + // ignore: avoid_dynamic_calls + expect((paint.painter as dynamic).dividerColor, dividerColor); }); testWidgets('Default TabAlignment', (WidgetTester tester) async { @@ -6479,43 +6259,6 @@ void main() { ), ); }); - - testWidgets('TabAlignment updates tabs alignment (non-scrollable TabBar)', (WidgetTester tester) async { - final ThemeData theme = ThemeData(useMaterial3: false); - final List tabs = ['A', 'B']; - - // Test TabAlignment.fill (default) when isScrollable is false. - await tester.pumpWidget(MaterialApp( - theme: theme, - home: buildFrame(tabs: tabs, value: 'B'), - )); - - final Rect tabBar = tester.getRect(find.byType(TabBar)); - Rect tabOneRect = tester.getRect(find.byType(Tab).first); - Rect tabTwoRect = tester.getRect(find.byType(Tab).last); - - // By default tabs should fill the width of the TabBar. - double tabOneLeft = ((tabBar.width / 2) - tabOneRect.width) / 2; - expect(tabOneRect.left, equals(tabOneLeft)); - double tabTwoRight = tabBar.width - ((tabBar.width / 2) - tabTwoRect.width) / 2; - expect(tabTwoRect.right, equals(tabTwoRight)); - - // Test TabAlignment.center when isScrollable is false. - await tester.pumpWidget(MaterialApp( - theme: theme, - home: buildFrame(tabs: tabs, value: 'B', tabAlignment: TabAlignment.center), - )); - await tester.pumpAndSettle(); - - tabOneRect = tester.getRect(find.byType(Tab).first); - tabTwoRect = tester.getRect(find.byType(Tab).last); - - // Tabs should not fill the width of the TabBar. - tabOneLeft = kTabLabelPadding.left; - expect(tabOneRect.left, equals(tabOneLeft)); - tabTwoRight = kTabLabelPadding.horizontal + tabOneRect.width + kTabLabelPadding.left + tabTwoRect.width; - expect(tabTwoRect.right, equals(tabTwoRight)); - }); }); }