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 { ...@@ -29,6 +29,7 @@ class TabBarTheme extends Diagnosticable {
this.indicator, this.indicator,
this.indicatorSize, this.indicatorSize,
this.labelColor, this.labelColor,
this.labelPadding,
this.labelStyle, this.labelStyle,
this.unselectedLabelColor, this.unselectedLabelColor,
this.unselectedLabelStyle, this.unselectedLabelStyle,
...@@ -43,6 +44,9 @@ class TabBarTheme extends Diagnosticable { ...@@ -43,6 +44,9 @@ class TabBarTheme extends Diagnosticable {
/// Default value for [TabBar.labelColor]. /// Default value for [TabBar.labelColor].
final Color labelColor; final Color labelColor;
/// Default value for [TabBar.labelPadding].
final EdgeInsetsGeometry labelPadding;
/// Default value for [TabBar.labelStyle]. /// Default value for [TabBar.labelStyle].
final TextStyle labelStyle; final TextStyle labelStyle;
...@@ -58,6 +62,7 @@ class TabBarTheme extends Diagnosticable { ...@@ -58,6 +62,7 @@ class TabBarTheme extends Diagnosticable {
Decoration indicator, Decoration indicator,
TabBarIndicatorSize indicatorSize, TabBarIndicatorSize indicatorSize,
Color labelColor, Color labelColor,
EdgeInsetsGeometry labelPadding,
TextStyle labelStyle, TextStyle labelStyle,
Color unselectedLabelColor, Color unselectedLabelColor,
TextStyle unselectedLabelStyle, TextStyle unselectedLabelStyle,
...@@ -66,6 +71,7 @@ class TabBarTheme extends Diagnosticable { ...@@ -66,6 +71,7 @@ class TabBarTheme extends Diagnosticable {
indicator: indicator ?? this.indicator, indicator: indicator ?? this.indicator,
indicatorSize: indicatorSize ?? this.indicatorSize, indicatorSize: indicatorSize ?? this.indicatorSize,
labelColor: labelColor ?? this.labelColor, labelColor: labelColor ?? this.labelColor,
labelPadding: labelPadding ?? this.labelPadding,
labelStyle: labelStyle ?? this.labelStyle, labelStyle: labelStyle ?? this.labelStyle,
unselectedLabelColor: unselectedLabelColor ?? this.unselectedLabelColor, unselectedLabelColor: unselectedLabelColor ?? this.unselectedLabelColor,
unselectedLabelStyle: unselectedLabelStyle ?? this.unselectedLabelStyle, unselectedLabelStyle: unselectedLabelStyle ?? this.unselectedLabelStyle,
...@@ -90,6 +96,7 @@ class TabBarTheme extends Diagnosticable { ...@@ -90,6 +96,7 @@ class TabBarTheme extends Diagnosticable {
indicator: Decoration.lerp(a.indicator, b.indicator, t), indicator: Decoration.lerp(a.indicator, b.indicator, t),
indicatorSize: t < 0.5 ? a.indicatorSize : b.indicatorSize, indicatorSize: t < 0.5 ? a.indicatorSize : b.indicatorSize,
labelColor: Color.lerp(a.labelColor, b.labelColor, t), labelColor: Color.lerp(a.labelColor, b.labelColor, t),
labelPadding: EdgeInsets.lerp(a.labelPadding, b.labelPadding, t),
labelStyle: TextStyle.lerp(a.labelStyle, b.labelStyle, t), labelStyle: TextStyle.lerp(a.labelStyle, b.labelStyle, t),
unselectedLabelColor: Color.lerp(a.unselectedLabelColor, b.unselectedLabelColor, t), unselectedLabelColor: Color.lerp(a.unselectedLabelColor, b.unselectedLabelColor, t),
unselectedLabelStyle: TextStyle.lerp(a.unselectedLabelStyle, b.unselectedLabelStyle, t), unselectedLabelStyle: TextStyle.lerp(a.unselectedLabelStyle, b.unselectedLabelStyle, t),
...@@ -102,6 +109,7 @@ class TabBarTheme extends Diagnosticable { ...@@ -102,6 +109,7 @@ class TabBarTheme extends Diagnosticable {
indicator, indicator,
indicatorSize, indicatorSize,
labelColor, labelColor,
labelPadding,
labelStyle, labelStyle,
unselectedLabelColor, unselectedLabelColor,
unselectedLabelStyle, unselectedLabelStyle,
...@@ -118,6 +126,7 @@ class TabBarTheme extends Diagnosticable { ...@@ -118,6 +126,7 @@ class TabBarTheme extends Diagnosticable {
return typedOther.indicator == indicator return typedOther.indicator == indicator
&& typedOther.indicatorSize == indicatorSize && typedOther.indicatorSize == indicatorSize
&& typedOther.labelColor == labelColor && typedOther.labelColor == labelColor
&& typedOther.labelPadding == labelPadding
&& typedOther.labelStyle == labelStyle && typedOther.labelStyle == labelStyle
&& typedOther.unselectedLabelColor == unselectedLabelColor && typedOther.unselectedLabelColor == unselectedLabelColor
&& typedOther.unselectedLabelStyle == unselectedLabelStyle; && typedOther.unselectedLabelStyle == unselectedLabelStyle;
......
...@@ -952,12 +952,14 @@ class _TabBarState extends State<TabBar> { ...@@ -952,12 +952,14 @@ class _TabBarState extends State<TabBar> {
); );
} }
final TabBarTheme tabBarTheme = TabBarTheme.of(context);
final List<Widget> wrappedTabs = List<Widget>(widget.tabs.length); final List<Widget> wrappedTabs = List<Widget>(widget.tabs.length);
for (int i = 0; i < widget.tabs.length; i += 1) { for (int i = 0; i < widget.tabs.length; i += 1) {
wrappedTabs[i] = Center( wrappedTabs[i] = Center(
heightFactor: 1.0, heightFactor: 1.0,
child: Padding( child: Padding(
padding: widget.labelPadding ?? kTabLabelPadding, padding: widget.labelPadding ?? tabBarTheme.labelPadding ?? kTabLabelPadding,
child: KeyedSubtree( child: KeyedSubtree(
key: _tabKeys[i], key: _tabKeys[i],
child: widget.tabs[i], child: widget.tabs[i],
......
...@@ -20,15 +20,22 @@ const List<Tab> _tabs = <Tab>[ ...@@ -20,15 +20,22 @@ const List<Tab> _tabs = <Tab>[
Tab(text: _tab3Text, icon: Icon(Icons.looks_3)), 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( return MaterialApp(
theme: ThemeData(tabBarTheme: theme), theme: ThemeData(tabBarTheme: theme),
home: Scaffold( home: Scaffold(
body: RepaintBoundary( body: RepaintBoundary(
key: _painterKey, key: _painterKey,
child: TabBar( child: TabBar(
tabs: _tabs, tabs: tabs,
controller: TabController(length: _tabs.length, vsync: const TestVSync()), isScrollable: isScrollable,
controller: TabController(length: tabs.length, vsync: const TestVSync()),
), ),
), ),
), ),
...@@ -41,7 +48,8 @@ RenderParagraph _iconRenderObject(WidgetTester tester, IconData icon) { ...@@ -41,7 +48,8 @@ RenderParagraph _iconRenderObject(WidgetTester tester, IconData icon) {
} }
void main() { 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)); await tester.pumpWidget(_withTheme(null));
final RenderParagraph selectedRenderObject = tester.renderObject<RenderParagraph>(find.text(_tab1Text)); final RenderParagraph selectedRenderObject = tester.renderObject<RenderParagraph>(find.text(_tab1Text));
...@@ -52,8 +60,28 @@ void main() { ...@@ -52,8 +60,28 @@ void main() {
expect(unselectedRenderObject.text.style.fontFamily, equals('Roboto')); expect(unselectedRenderObject.text.style.fontFamily, equals('Roboto'));
expect(unselectedRenderObject.text.style.fontSize, equals(14.0)); expect(unselectedRenderObject.text.style.fontSize, equals(14.0));
expect(unselectedRenderObject.text.style.color, equals(Colors.white.withAlpha(0xB2))); 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 { testWidgets('Tab bar theme overrides label color (selected)', (WidgetTester tester) async {
const Color labelColor = Colors.black; const Color labelColor = Colors.black;
const TabBarTheme tabBarTheme = TabBarTheme(labelColor: labelColor); const TabBarTheme tabBarTheme = TabBarTheme(labelColor: labelColor);
...@@ -66,6 +94,43 @@ void main() { ...@@ -66,6 +94,43 @@ void main() {
expect(iconRenderObject.text.style.color, equals(labelColor)); 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 { testWidgets('Tab bar theme overrides label styles', (WidgetTester tester) async {
const TextStyle labelStyle = TextStyle(fontFamily: 'foobar'); const TextStyle labelStyle = TextStyle(fontFamily: 'foobar');
const TextStyle unselectedLabelStyle = TextStyle(fontFamily: 'baz'); const TextStyle unselectedLabelStyle = TextStyle(fontFamily: 'baz');
...@@ -128,6 +193,60 @@ void main() { ...@@ -128,6 +193,60 @@ void main() {
expect(unselectedRenderObject.text.style.fontFamily, equals(unselectedLabelStyle.fontFamily)); 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 { testWidgets('Tab bar theme overrides label color (unselected)', (WidgetTester tester) async {
const Color unselectedLabelColor = Colors.black; const Color unselectedLabelColor = Colors.black;
const TabBarTheme tabBarTheme = TabBarTheme(unselectedLabelColor: unselectedLabelColor); 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