Skip to content

Commit

Permalink
Fix transparent dividerColor breaks TabBar.tabAlignment (#150350)
Browse files Browse the repository at this point in the history
fixes [`TabBar.tabAlignment` property does't work when `dividerColor` is transparent](flutter/flutter#150316)

### Code sample

<details>
<summary>expand to view the code sample</summary> 

```dart
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @OverRide
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: DefaultTabController(
        length: 2,
        child: Scaffold(
          appBar: AppBar(
            title: const Text('TabBar'),
            bottom: const TabBar(
              dividerColor: Colors.transparent,
              tabAlignment: TabAlignment.start,
              isScrollable: true,
              tabs: <Widget>[
                Tab(text: 'TAB 1'),
                Tab(text: 'TAB 2'),
              ],
            ),
          ),
          body: const TabBarView(
            children: <Widget>[
              SizedBox.expand(),
              SizedBox.expand(),
            ],
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () {},
            child: const Icon(Icons.add),
          ),
        ),
      ),
    );
  }
}
```

</details>

### Before (`dividerColor: Colors.transparent`, `tabAlignment: TabAlignment.start`)

![Screenshot 2024-06-17 at 15 44 33](https://github.com/flutter/flutter/assets/48603081/a60e88c7-fd99-4444-b7e5-1bceacc22f4c)

### After (`dividerColor: Colors.transparent`, `tabAlignment: TabAlignment.start`)

![Screenshot 2024-06-17 at 15 44 55](https://github.com/flutter/flutter/assets/48603081/aa003d65-107f-4618-be29-095ab2660374)
  • Loading branch information
TahaTesser authored Jun 18, 2024
1 parent a9f554a commit 3359900
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 28 deletions.
11 changes: 7 additions & 4 deletions packages/flutter/lib/src/material/tabs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1025,13 +1025,17 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {

/// The color of the divider.
///
/// If the [dividerColor] is [Colors.transparent], then the divider will not be drawn.
///
/// If null and [ThemeData.useMaterial3] is false, [TabBarTheme.dividerColor]
/// color is used. If that is null and [ThemeData.useMaterial3] is true,
/// [ColorScheme.outlineVariant] will be used, otherwise divider will not be drawn.
final Color? dividerColor;

/// The height of the divider.
///
/// If the [dividerHeight] is zero or negative, then the divider will not be drawn.
///
/// 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.
Expand Down Expand Up @@ -1813,19 +1817,18 @@ class _TabBarState extends State<TabBar> {

final Color dividerColor = widget.dividerColor ?? tabBarTheme.dividerColor ?? _defaults.dividerColor!;
final double dividerHeight = widget.dividerHeight ?? tabBarTheme.dividerHeight ?? _defaults.dividerHeight!;
final bool showDivider = dividerColor != Colors.transparent && dividerHeight > 0;

tabBar = Align(
heightFactor: 1.0,
widthFactor: showDivider ? null : 1.0,
widthFactor: dividerHeight > 0 ? null : 1.0,
alignment: effectiveAlignment,
child: tabBar,
);

if (showDivider) {
if (dividerColor != Colors.transparent && dividerHeight > 0) {
tabBar = CustomPaint(
painter: _DividerPainter(
dividerColor: widget.dividerColor ?? tabBarTheme.dividerColor ?? _defaults.dividerColor!,
dividerColor: dividerColor,
dividerHeight: widget.dividerHeight ?? tabBarTheme.dividerHeight ?? _defaults.dividerHeight!,
),
child: tabBar,
Expand Down
71 changes: 47 additions & 24 deletions packages/flutter/test/material/tabs_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6722,30 +6722,6 @@ void main() {
tabAlignment: TabAlignment.center,
));
expect(tester.getSize(find.byType(TabBar)).width, 307.5);

// Test default tab bar width when the divider color is set to transparent
// and tabAlignment is set to startOffset.
await tester.pumpWidget(buildTabBar(
dividerColor: Colors.transparent,
tabAlignment: TabAlignment.startOffset,
));
expect(tester.getSize(find.byType(TabBar)).width, 359.5);

// Test default tab bar width when the divider color is set to transparent
// and tabAlignment is set to start.
await tester.pumpWidget(buildTabBar(
dividerColor: Colors.transparent,
tabAlignment: TabAlignment.start,
));
expect(tester.getSize(find.byType(TabBar)).width, 307.5);

// Test default tab bar width when the divider color is set to transparent
// and tabAlignment is set to center.
await tester.pumpWidget(buildTabBar(
dividerColor: Colors.transparent,
tabAlignment: TabAlignment.center,
));
expect(tester.getSize(find.byType(TabBar)).width, 307.5);
});

group('Material 2', () {
Expand Down Expand Up @@ -7250,4 +7226,51 @@ void main() {
expect(find.text('Page 3'), findsOneWidget);
expect(scrollable.controller!.position.pixels, equals(0.0));
});

// This is a regression test for https://github.com/flutter/flutter/issues/150316.
testWidgets('Scrollable TabBar wuth transparent divider expands to full width', (WidgetTester tester) async {
Widget buildTabBar({ Color? dividerColor, TabAlignment? tabAlignment }) {
return boilerplate(
child: Center(
child: DefaultTabController(
length: 3,
child: TabBar(
dividerColor: dividerColor,
tabAlignment: tabAlignment,
isScrollable: true,
tabs: const <Widget>[
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
Tab(text: 'Tab 3'),
],
),
),
),
);
}

// Test default tab bar width when the divider color is set to transparent
// and tabAlignment is set to startOffset.
await tester.pumpWidget(buildTabBar(
dividerColor: Colors.transparent,
tabAlignment: TabAlignment.startOffset,
));
expect(tester.getSize(find.byType(TabBar)).width, 800.0);

// Test default tab bar width when the divider color is set to transparent
// and tabAlignment is set to start.
await tester.pumpWidget(buildTabBar(
dividerColor: Colors.transparent,
tabAlignment: TabAlignment.start,
));
expect(tester.getSize(find.byType(TabBar)).width, 800.0);

// Test default tab bar width when the divider color is set to transparent
// and tabAlignment is set to center.
await tester.pumpWidget(buildTabBar(
dividerColor: Colors.transparent,
tabAlignment: TabAlignment.center,
));
expect(tester.getSize(find.byType(TabBar)).width, 800.0);
});
}

0 comments on commit 3359900

Please sign in to comment.