Unverified Commit c942ed48 authored by Shi-Hao Hong's avatar Shi-Hao Hong Committed by GitHub

Implement labelPadding configuration in TabBarTheme (#29183)

parent 4e842566
......@@ -29,6 +29,7 @@ class TabBarTheme extends Diagnosticable {
this.indicator,
this.indicatorSize,
this.labelColor,
this.labelPadding,
this.labelStyle,
this.unselectedLabelColor,
this.unselectedLabelStyle,
......@@ -43,6 +44,9 @@ class TabBarTheme extends Diagnosticable {
/// Default value for [TabBar.labelColor].
final Color labelColor;
/// Default value for [TabBar.labelPadding].
final EdgeInsetsGeometry labelPadding;
/// Default value for [TabBar.labelStyle].
final TextStyle labelStyle;
......@@ -58,6 +62,7 @@ class TabBarTheme extends Diagnosticable {
Decoration indicator,
TabBarIndicatorSize indicatorSize,
Color labelColor,
EdgeInsetsGeometry labelPadding,
TextStyle labelStyle,
Color unselectedLabelColor,
TextStyle unselectedLabelStyle,
......@@ -66,6 +71,7 @@ class TabBarTheme extends Diagnosticable {
indicator: indicator ?? this.indicator,
indicatorSize: indicatorSize ?? this.indicatorSize,
labelColor: labelColor ?? this.labelColor,
labelPadding: labelPadding ?? this.labelPadding,
labelStyle: labelStyle ?? this.labelStyle,
unselectedLabelColor: unselectedLabelColor ?? this.unselectedLabelColor,
unselectedLabelStyle: unselectedLabelStyle ?? this.unselectedLabelStyle,
......@@ -90,6 +96,7 @@ class TabBarTheme extends Diagnosticable {
indicator: Decoration.lerp(a.indicator, b.indicator, t),
indicatorSize: t < 0.5 ? a.indicatorSize : b.indicatorSize,
labelColor: Color.lerp(a.labelColor, b.labelColor, t),
labelPadding: EdgeInsets.lerp(a.labelPadding, b.labelPadding, t),
labelStyle: TextStyle.lerp(a.labelStyle, b.labelStyle, t),
unselectedLabelColor: Color.lerp(a.unselectedLabelColor, b.unselectedLabelColor, t),
unselectedLabelStyle: TextStyle.lerp(a.unselectedLabelStyle, b.unselectedLabelStyle, t),
......@@ -102,6 +109,7 @@ class TabBarTheme extends Diagnosticable {
indicator,
indicatorSize,
labelColor,
labelPadding,
labelStyle,
unselectedLabelColor,
unselectedLabelStyle,
......@@ -118,6 +126,7 @@ class TabBarTheme extends Diagnosticable {
return typedOther.indicator == indicator
&& typedOther.indicatorSize == indicatorSize
&& typedOther.labelColor == labelColor
&& typedOther.labelPadding == labelPadding
&& typedOther.labelStyle == labelStyle
&& typedOther.unselectedLabelColor == unselectedLabelColor
&& typedOther.unselectedLabelStyle == unselectedLabelStyle;
......
......@@ -952,12 +952,14 @@ class _TabBarState extends State<TabBar> {
);
}
final TabBarTheme tabBarTheme = TabBarTheme.of(context);
final List<Widget> wrappedTabs = List<Widget>(widget.tabs.length);
for (int i = 0; i < widget.tabs.length; i += 1) {
wrappedTabs[i] = Center(
heightFactor: 1.0,
child: Padding(
padding: widget.labelPadding ?? kTabLabelPadding,
padding: widget.labelPadding ?? tabBarTheme.labelPadding ?? kTabLabelPadding,
child: KeyedSubtree(
key: _tabKeys[i],
child: widget.tabs[i],
......
......@@ -20,15 +20,22 @@ const List<Tab> _tabs = <Tab>[
Tab(text: _tab3Text, icon: Icon(Icons.looks_3)),
];
Widget _withTheme(TabBarTheme theme) {
final List<SizedBox> _sizedTabs = <SizedBox>[
SizedBox(key: UniqueKey(), width: 100.0, height: 50.0),
SizedBox(key: UniqueKey(), width: 100.0, height: 50.0),
];
Widget _withTheme(
TabBarTheme theme, { List<Widget> tabs = _tabs, bool isScrollable = false }) {
return MaterialApp(
theme: ThemeData(tabBarTheme: theme),
home: Scaffold(
body: RepaintBoundary(
key: _painterKey,
child: TabBar(
tabs: _tabs,
controller: TabController(length: _tabs.length, vsync: const TestVSync()),
tabs: tabs,
isScrollable: isScrollable,
controller: TabController(length: tabs.length, vsync: const TestVSync()),
),
),
),
......@@ -41,7 +48,8 @@ RenderParagraph _iconRenderObject(WidgetTester tester, IconData icon) {
}
void main() {
testWidgets('Tab bar defaults', (WidgetTester tester) async {
testWidgets('Tab bar defaults - label style and selected/unselected label colors', (WidgetTester tester) async {
// tests for the default label color and label styles when tabBarTheme and tabBar do not provide any
await tester.pumpWidget(_withTheme(null));
final RenderParagraph selectedRenderObject = tester.renderObject<RenderParagraph>(find.text(_tab1Text));
......@@ -52,8 +60,28 @@ void main() {
expect(unselectedRenderObject.text.style.fontFamily, equals('Roboto'));
expect(unselectedRenderObject.text.style.fontSize, equals(14.0));
expect(unselectedRenderObject.text.style.color, equals(Colors.white.withAlpha(0xB2)));
});
// tests for the default value of labelPadding when tabBarTheme and tabBar do not provide one
await tester.pumpWidget(_withTheme(null, tabs: _sizedTabs, isScrollable: true));
const double indicatorWeight = 2.0;
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));
// verify coordinates of tabOne
expect(tabOneRect.left, equals(kTabLabelPadding.left));
expect(tabOneRect.top, equals(kTabLabelPadding.top));
expect(tabOneRect.bottom, equals(tabBar.bottom - kTabLabelPadding.bottom - indicatorWeight));
// verify coordinates of tabTwo
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 is separated by right padding of tabOne and left padding of tabTwo
expect(tabOneRect.right, equals(tabTwoRect.left - kTabLabelPadding.left - kTabLabelPadding.right));
});
testWidgets('Tab bar theme overrides label color (selected)', (WidgetTester tester) async {
const Color labelColor = Colors.black;
const TabBarTheme tabBarTheme = TabBarTheme(labelColor: labelColor);
......@@ -66,6 +94,43 @@ void main() {
expect(iconRenderObject.text.style.color, equals(labelColor));
});
testWidgets('Tab bar theme overrides label padding', (WidgetTester tester) async {
const double topPadding = 10.0;
const double bottomPadding = 7.0;
const double rightPadding = 13.0;
const double leftPadding = 16.0;
const double indicatorWeight = 2.0; // default value
const EdgeInsetsGeometry labelPadding = EdgeInsets.fromLTRB(
leftPadding, topPadding, rightPadding, bottomPadding
);
const TabBarTheme tabBarTheme = TabBarTheme(labelPadding: labelPadding);
await tester.pumpWidget(_withTheme(
tabBarTheme,
tabs: _sizedTabs,
isScrollable: true,
));
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));
// verify coordinates of tabOne
expect(tabOneRect.left, equals(leftPadding));
expect(tabOneRect.top, equals(topPadding));
expect(tabOneRect.bottom, equals(tabBar.bottom - bottomPadding - indicatorWeight));
// verify coordinates of tabTwo
expect(tabTwoRect.right, equals(tabBar.width - rightPadding));
expect(tabTwoRect.top, equals(topPadding));
expect(tabTwoRect.bottom, equals(tabBar.bottom - bottomPadding - indicatorWeight));
// verify tabOne and tabTwo are separated by right padding of tabOne and left padding of tabTwo
expect(tabOneRect.right, equals(tabTwoRect.left - leftPadding - rightPadding));
});
testWidgets('Tab bar theme overrides label styles', (WidgetTester tester) async {
const TextStyle labelStyle = TextStyle(fontFamily: 'foobar');
const TextStyle unselectedLabelStyle = TextStyle(fontFamily: 'baz');
......@@ -128,6 +193,60 @@ void main() {
expect(unselectedRenderObject.text.style.fontFamily, equals(unselectedLabelStyle.fontFamily));
});
testWidgets('Tab bar label padding overrides theme label padding', (WidgetTester tester) async {
const double verticalPadding = 10.0;
const double horizontalPadding = 10.0;
const EdgeInsetsGeometry labelPadding = EdgeInsets.symmetric(
vertical: verticalPadding,
horizontal: horizontalPadding,
);
const double verticalThemePadding = 20.0;
const double horizontalThemePadding = 20.0;
const EdgeInsetsGeometry themeLabelPadding = EdgeInsets.symmetric(
vertical: verticalThemePadding,
horizontal: horizontalThemePadding,
);
const double indicatorWeight = 2.0; // default value
const TabBarTheme tabBarTheme = TabBarTheme(labelPadding: themeLabelPadding);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(tabBarTheme: tabBarTheme),
home: Scaffold(body:
RepaintBoundary(
key: _painterKey,
child: TabBar(
tabs: _sizedTabs,
isScrollable: true,
controller: TabController(length: _sizedTabs.length, vsync: const TestVSync()),
labelPadding: labelPadding,
),
),
),
),
);
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));
// verify coordinates of tabOne
expect(tabOneRect.left, equals(horizontalPadding));
expect(tabOneRect.top, equals(verticalPadding));
expect(tabOneRect.bottom, equals(tabBar.bottom - verticalPadding - indicatorWeight));
// verify coordinates of tabTwo
expect(tabTwoRect.right, equals(tabBar.width - horizontalPadding));
expect(tabTwoRect.top, equals(verticalPadding));
expect(tabTwoRect.bottom, equals(tabBar.bottom - verticalPadding - indicatorWeight));
// verify tabOne and tabTwo are separated by 2x horizontalPadding
expect(tabOneRect.right, equals(tabTwoRect.left - (2 * horizontalPadding)));
});
testWidgets('Tab bar theme overrides label color (unselected)', (WidgetTester tester) async {
const Color unselectedLabelColor = Colors.black;
const TabBarTheme tabBarTheme = TabBarTheme(unselectedLabelColor: unselectedLabelColor);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment