Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
378668db
Unverified
Commit
378668db
authored
Feb 15, 2023
by
Viren Khatri
Committed by
GitHub
Feb 15, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added MaterialStateColor support to TabBarTheme.labelColor (#109541)
parent
d29668dd
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
290 additions
and
54 deletions
+290
-54
tab_bar_theme.dart
packages/flutter/lib/src/material/tab_bar_theme.dart
+6
-0
tabs.dart
packages/flutter/lib/src/material/tabs.dart
+96
-35
tabs_test.dart
packages/flutter/test/material/tabs_test.dart
+188
-19
No files found.
packages/flutter/lib/src/material/tab_bar_theme.dart
View file @
378668db
...
@@ -55,6 +55,12 @@ class TabBarTheme with Diagnosticable {
...
@@ -55,6 +55,12 @@ class TabBarTheme with Diagnosticable {
final
Color
?
dividerColor
;
final
Color
?
dividerColor
;
/// Overrides the default value for [TabBar.labelColor].
/// Overrides the default value for [TabBar.labelColor].
///
/// If [labelColor] is a [MaterialStateColor], then the effective color will
/// depend on the [MaterialState.selected] state, i.e. if the [Tab] is
/// selected or not. In case of unselected state, this [MaterialStateColor]'s
/// resolved color will be used even if [TabBar.unselectedLabelColor] or
/// [unselectedLabelColor] is non-null.
final
Color
?
labelColor
;
final
Color
?
labelColor
;
/// Overrides the default value for [TabBar.labelPadding].
/// Overrides the default value for [TabBar.labelPadding].
...
...
packages/flutter/lib/src/material/tabs.dart
View file @
378668db
...
@@ -166,7 +166,7 @@ class Tab extends StatelessWidget implements PreferredSizeWidget {
...
@@ -166,7 +166,7 @@ class Tab extends StatelessWidget implements PreferredSizeWidget {
class
_TabStyle
extends
AnimatedWidget
{
class
_TabStyle
extends
AnimatedWidget
{
const
_TabStyle
({
const
_TabStyle
({
required
Animation
<
double
>
animation
,
required
Animation
<
double
>
animation
,
required
this
.
s
elected
,
required
this
.
isS
elected
,
required
this
.
labelColor
,
required
this
.
labelColor
,
required
this
.
unselectedLabelColor
,
required
this
.
unselectedLabelColor
,
required
this
.
labelStyle
,
required
this
.
labelStyle
,
...
@@ -176,11 +176,47 @@ class _TabStyle extends AnimatedWidget {
...
@@ -176,11 +176,47 @@ class _TabStyle extends AnimatedWidget {
final
TextStyle
?
labelStyle
;
final
TextStyle
?
labelStyle
;
final
TextStyle
?
unselectedLabelStyle
;
final
TextStyle
?
unselectedLabelStyle
;
final
bool
s
elected
;
final
bool
isS
elected
;
final
Color
?
labelColor
;
final
Color
?
labelColor
;
final
Color
?
unselectedLabelColor
;
final
Color
?
unselectedLabelColor
;
final
Widget
child
;
final
Widget
child
;
MaterialStateColor
_resolveWithLabelColor
(
BuildContext
context
)
{
final
ThemeData
themeData
=
Theme
.
of
(
context
);
final
TabBarTheme
tabBarTheme
=
TabBarTheme
.
of
(
context
);
final
TabBarTheme
defaults
=
themeData
.
useMaterial3
?
_TabsDefaultsM3
(
context
)
:
_TabsDefaultsM2
(
context
);
final
Animation
<
double
>
animation
=
listenable
as
Animation
<
double
>;
// labelStyle.color (and tabBarTheme.labelStyle.color) is not considered
// as it'll be a breaking change without a possible migration plan. for
// details: https://github.com/flutter/flutter/pull/109541#issuecomment-1294241417
Color
selectedColor
=
labelColor
??
tabBarTheme
.
labelColor
??
defaults
.
labelColor
!;
final
Color
unselectedColor
;
if
(
selectedColor
is
MaterialStateColor
)
{
unselectedColor
=
selectedColor
.
resolve
(
const
<
MaterialState
>{});
selectedColor
=
selectedColor
.
resolve
(
const
<
MaterialState
>{
MaterialState
.
selected
});
}
else
{
// unselectedLabelColor and tabBarTheme.unselectedLabelColor are ignored
// when labelColor is a MaterialStateColor.
unselectedColor
=
unselectedLabelColor
??
tabBarTheme
.
unselectedLabelColor
??
(
themeData
.
useMaterial3
?
defaults
.
unselectedLabelColor
!
:
selectedColor
.
withAlpha
(
0xB2
));
// 70% alpha
}
return
MaterialStateColor
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
Color
.
lerp
(
selectedColor
,
unselectedColor
,
animation
.
value
)!;
}
return
Color
.
lerp
(
unselectedColor
,
selectedColor
,
animation
.
value
)!;
});
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
ThemeData
themeData
=
Theme
.
of
(
context
);
final
ThemeData
themeData
=
Theme
.
of
(
context
);
...
@@ -188,6 +224,10 @@ class _TabStyle extends AnimatedWidget {
...
@@ -188,6 +224,10 @@ class _TabStyle extends AnimatedWidget {
final
TabBarTheme
defaults
=
themeData
.
useMaterial3
?
_TabsDefaultsM3
(
context
)
:
_TabsDefaultsM2
(
context
);
final
TabBarTheme
defaults
=
themeData
.
useMaterial3
?
_TabsDefaultsM3
(
context
)
:
_TabsDefaultsM2
(
context
);
final
Animation
<
double
>
animation
=
listenable
as
Animation
<
double
>;
final
Animation
<
double
>
animation
=
listenable
as
Animation
<
double
>;
final
Set
<
MaterialState
>
states
=
isSelected
?
const
<
MaterialState
>{
MaterialState
.
selected
}
:
const
<
MaterialState
>{};
// To enable TextStyle.lerp(style1, style2, value), both styles must have
// To enable TextStyle.lerp(style1, style2, value), both styles must have
// the same value of inherit. Force that to be inherit=true here.
// the same value of inherit. Force that to be inherit=true here.
final
TextStyle
defaultStyle
=
(
labelStyle
final
TextStyle
defaultStyle
=
(
labelStyle
...
@@ -199,21 +239,10 @@ class _TabStyle extends AnimatedWidget {
...
@@ -199,21 +239,10 @@ class _TabStyle extends AnimatedWidget {
??
labelStyle
??
labelStyle
??
defaults
.
unselectedLabelStyle
!
??
defaults
.
unselectedLabelStyle
!
).
copyWith
(
inherit:
true
);
).
copyWith
(
inherit:
true
);
final
TextStyle
textStyle
=
s
elected
final
TextStyle
textStyle
=
isS
elected
?
TextStyle
.
lerp
(
defaultStyle
,
defaultUnselectedStyle
,
animation
.
value
)!
?
TextStyle
.
lerp
(
defaultStyle
,
defaultUnselectedStyle
,
animation
.
value
)!
:
TextStyle
.
lerp
(
defaultUnselectedStyle
,
defaultStyle
,
animation
.
value
)!;
:
TextStyle
.
lerp
(
defaultUnselectedStyle
,
defaultStyle
,
animation
.
value
)!;
final
Color
color
=
_resolveWithLabelColor
(
context
).
resolve
(
states
);
final
Color
selectedColor
=
labelColor
??
tabBarTheme
.
labelColor
??
defaults
.
labelColor
!;
final
Color
unselectedColor
=
unselectedLabelColor
??
tabBarTheme
.
unselectedLabelColor
??
(
themeData
.
useMaterial3
?
defaults
.
unselectedLabelColor
!
:
selectedColor
.
withAlpha
(
0xB2
));
// 70% alpha
final
Color
color
=
selected
?
Color
.
lerp
(
selectedColor
,
unselectedColor
,
animation
.
value
)!
:
Color
.
lerp
(
unselectedColor
,
selectedColor
,
animation
.
value
)!;
return
DefaultTextStyle
(
return
DefaultTextStyle
(
style:
textStyle
.
copyWith
(
color:
color
),
style:
textStyle
.
copyWith
(
color:
color
),
...
@@ -738,7 +767,8 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
...
@@ -738,7 +767,8 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
///
///
/// If [automaticIndicatorColorAdjustment] is true,
/// If [automaticIndicatorColorAdjustment] is true,
/// then the [indicatorColor] will be automatically adjusted to [Colors.white]
/// then the [indicatorColor] will be automatically adjusted to [Colors.white]
/// when the [indicatorColor] is same as [Material.color] of the [Material] parent widget.
/// when the [indicatorColor] is same as [Material.color] of the [Material]
/// parent widget.
final
bool
automaticIndicatorColorAdjustment
;
final
bool
automaticIndicatorColorAdjustment
;
/// Defines how the selected tab indicator's size is computed.
/// Defines how the selected tab indicator's size is computed.
...
@@ -762,23 +792,50 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
...
@@ -762,23 +792,50 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
/// The color of selected tab labels.
/// The color of selected tab labels.
///
///
/// If [ThemeData.useMaterial3] is false, unselected tab labels are rendered with
/// If null, then [TabBarTheme.labelColor] is used. If that is also null and
/// the same color with 70% opacity unless [unselectedLabelColor] is non-null.
/// [ThemeData.useMaterial3] is true, [ColorScheme.primary] will be used,
///
/// otherwise the color of the [ThemeData.primaryTextTheme]'s
/// If this property is null and [ThemeData.useMaterial3] is true, [ColorScheme.primary]
/// will be used, otherwise the color of the [ThemeData.primaryTextTheme]'s
/// [TextTheme.bodyLarge] text color is used.
/// [TextTheme.bodyLarge] text color is used.
///
/// If [labelColor] (or, if null, [TabBarTheme.labelColor]) is a
/// [MaterialStateColor], then the effective tab color will depend on the
/// [MaterialState.selected] state, i.e. if the [Tab] is selected or not,
/// ignoring [unselectedLabelColor] even if it's non-null.
///
/// Note: [labelStyle]'s color and [TabBarTheme.labelStyle]'s color do not
/// affect the effective [labelColor].
///
/// See also:
///
/// * [unselectedLabelColor], for color of unselected tab labels.
final
Color
?
labelColor
;
final
Color
?
labelColor
;
/// The color of unselected tab labels.
/// The color of unselected tab labels.
///
///
/// If this property is null and [ThemeData.useMaterial3] is true, [ColorScheme.onSurfaceVariant]
/// If [labelColor] (or, if null, [TabBarTheme.labelColor]) is a
/// will be used, otherwise unselected tab labels are rendered with the
/// [MaterialStateColor], then the unselected tabs are rendered with
/// [labelColor] with 70% opacity.
/// that [MaterialStateColor]'s resolved color for unselected state, even if
/// [unselectedLabelColor] is non-null.
///
/// If null, then [TabBarTheme.unselectedLabelColor] is used. If that is also
/// null and [ThemeData.useMaterial3] is true, [ColorScheme.onSurfaceVariant]
/// will be used, otherwise unselected tab labels are rendered with
/// [labelColor] at 70% opacity.
///
/// Note: [unselectedLabelStyle]'s color and
/// [TabBarTheme.unselectedLabelStyle]'s color are ignored in
/// [unselectedLabelColor]'s precedence calculation.
///
/// See also:
///
/// * [labelColor], for color of selected tab labels.
final
Color
?
unselectedLabelColor
;
final
Color
?
unselectedLabelColor
;
/// The text style of the selected tab labels.
/// The text style of the selected tab labels.
///
///
/// This does not influence color of the tab labels even if [TextStyle.color]
/// is non-null. Refer [labelColor] to color selected tab labels instead.
///
/// If [unselectedLabelStyle] is null, then this text style will be used for
/// If [unselectedLabelStyle] is null, then this text style will be used for
/// both selected and unselected label styles.
/// both selected and unselected label styles.
///
///
...
@@ -787,6 +844,18 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
...
@@ -787,6 +844,18 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
/// [TextTheme.bodyLarge] definition is used.
/// [TextTheme.bodyLarge] definition is used.
final
TextStyle
?
labelStyle
;
final
TextStyle
?
labelStyle
;
/// The text style of the unselected tab labels.
///
/// This does not influence color of the tab labels even if [TextStyle.color]
/// is non-null. Refer [unselectedLabelColor] to color unselected tab labels
/// instead.
///
/// If this property is null and [ThemeData.useMaterial3] is true,
/// [TextTheme.titleSmall] will be used, otherwise then the [labelStyle] value
/// is used. If [labelStyle] is null, the text style of the
/// [ThemeData.primaryTextTheme]'s [TextTheme.bodyLarge] definition is used.
final
TextStyle
?
unselectedLabelStyle
;
/// The padding added to each of the tab labels.
/// The padding added to each of the tab labels.
///
///
/// If there are few tabs with both icon and text and few
/// If there are few tabs with both icon and text and few
...
@@ -796,14 +865,6 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
...
@@ -796,14 +865,6 @@ class TabBar extends StatefulWidget implements PreferredSizeWidget {
/// If this property is null, then kTabLabelPadding is used.
/// If this property is null, then kTabLabelPadding is used.
final
EdgeInsetsGeometry
?
labelPadding
;
final
EdgeInsetsGeometry
?
labelPadding
;
/// The text style of the unselected tab labels.
///
/// If this property is null and [ThemeData.useMaterial3] is true, [TextTheme.titleSmall]
/// will be used, otherwise then the [labelStyle] value is used. If [labelStyle]
/// is null, the text style of the [ThemeData.primaryTextTheme]'s
/// [TextTheme.bodyLarge] definition is used.
final
TextStyle
?
unselectedLabelStyle
;
/// Defines the ink response focus, hover, and splash colors.
/// Defines the ink response focus, hover, and splash colors.
///
///
/// If non-null, it is resolved against one of [MaterialState.focused],
/// If non-null, it is resolved against one of [MaterialState.focused],
...
@@ -1209,10 +1270,10 @@ class _TabBarState extends State<TabBar> {
...
@@ -1209,10 +1270,10 @@ class _TabBarState extends State<TabBar> {
widget
.
onTap
?.
call
(
index
);
widget
.
onTap
?.
call
(
index
);
}
}
Widget
_buildStyledTab
(
Widget
child
,
bool
s
elected
,
Animation
<
double
>
animation
)
{
Widget
_buildStyledTab
(
Widget
child
,
bool
isS
elected
,
Animation
<
double
>
animation
)
{
return
_TabStyle
(
return
_TabStyle
(
animation:
animation
,
animation:
animation
,
selected:
s
elected
,
isSelected:
isS
elected
,
labelColor:
widget
.
labelColor
,
labelColor:
widget
.
labelColor
,
unselectedLabelColor:
widget
.
unselectedLabelColor
,
unselectedLabelColor:
widget
.
unselectedLabelColor
,
labelStyle:
widget
.
labelStyle
,
labelStyle:
widget
.
labelStyle
,
...
@@ -1368,7 +1429,7 @@ class _TabBarState extends State<TabBar> {
...
@@ -1368,7 +1429,7 @@ class _TabBarState extends State<TabBar> {
painter:
_indicatorPainter
,
painter:
_indicatorPainter
,
child:
_TabStyle
(
child:
_TabStyle
(
animation:
kAlwaysDismissedAnimation
,
animation:
kAlwaysDismissedAnimation
,
s
elected:
false
,
isS
elected:
false
,
labelColor:
widget
.
labelColor
,
labelColor:
widget
.
labelColor
,
unselectedLabelColor:
widget
.
unselectedLabelColor
,
unselectedLabelColor:
widget
.
unselectedLabelColor
,
labelStyle:
widget
.
labelStyle
,
labelStyle:
widget
.
labelStyle
,
...
...
packages/flutter/test/material/tabs_test.dart
View file @
378668db
...
@@ -3950,6 +3950,141 @@ void main() {
...
@@ -3950,6 +3950,141 @@ void main() {
expect
(
iconTheme
.
color
,
equals
(
selectedTabColor
));
expect
(
iconTheme
.
color
,
equals
(
selectedTabColor
));
});
});
testWidgets
(
'TabBar colors labels correctly'
,
(
WidgetTester
tester
)
async
{
MaterialStateColor
buildMSC
(
Color
selectedColor
,
Color
unselectedColor
)
{
return
MaterialStateColor
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
selectedColor
;
}
return
unselectedColor
;
});
}
final
Color
materialLabelColor
=
buildMSC
(
const
Color
(
0x00000000
),
const
Color
(
0x00000001
));
const
Color
labelColor
=
Color
(
0x00000002
);
const
Color
unselectedLabelColor
=
Color
(
0x00000003
);
// this is to make sure labelStyles (in TabBar and in TabBarTheme) don't
// affect label's color. for details: https://github.com/flutter/flutter/pull/109541#issuecomment-1294241417
const
TextStyle
labelStyle
=
TextStyle
(
color:
Color
(
0x00000004
));
const
TextStyle
unselectedLabelStyle
=
TextStyle
(
color:
Color
(
0x00000005
));
final
TabBarTheme
materialTabBarTheme
=
TabBarTheme
(
labelColor:
buildMSC
(
const
Color
(
0x00000006
),
const
Color
(
0x00000007
)),
unselectedLabelColor:
const
Color
(
0x00000008
),
labelStyle:
TextStyle
(
color:
buildMSC
(
const
Color
(
0x00000009
),
const
Color
(
0x00000010
))),
unselectedLabelStyle:
const
TextStyle
(
color:
Color
(
0x00000011
)),
);
const
TabBarTheme
tabBarTheme
=
TabBarTheme
(
labelColor:
Color
(
0x00000012
),
unselectedLabelColor:
Color
(
0x00000013
),
labelStyle:
TextStyle
(
color:
Color
(
0x00000014
)),
unselectedLabelStyle:
TextStyle
(
color:
Color
(
0x00000015
)),
);
const
TabBarTheme
tabBarThemeWithNullUnselectedLabelColor
=
TabBarTheme
(
labelColor:
Color
(
0x00000016
),
labelStyle:
TextStyle
(
color:
Color
(
0x00000017
)),
unselectedLabelStyle:
TextStyle
(
color:
Color
(
0x00000018
)),
);
Widget
buildTabBar
({
bool
isLabelColorMSC
=
false
,
bool
isLabelColorNull
=
false
,
bool
isUnselectedLabelColorNull
=
false
,
bool
isTabBarThemeMSC
=
false
,
bool
isTabBarThemeNull
=
false
,
bool
isTabBarThemeUnselectedLabelColorNull
=
false
,
})
{
final
TabBarTheme
?
effectiveTheme
=
isTabBarThemeNull
?
null
:
isTabBarThemeUnselectedLabelColorNull
?
tabBarThemeWithNullUnselectedLabelColor
:
isTabBarThemeMSC
?
materialTabBarTheme
:
tabBarTheme
;
return
boilerplate
(
child:
Theme
(
data:
ThemeData
(
tabBarTheme:
effectiveTheme
),
child:
DefaultTabController
(
length:
2
,
child:
TabBar
(
labelColor:
isLabelColorNull
?
null
:
isLabelColorMSC
?
materialLabelColor
:
labelColor
,
unselectedLabelColor:
isUnselectedLabelColorNull
?
null
:
unselectedLabelColor
,
labelStyle:
labelStyle
,
unselectedLabelStyle:
unselectedLabelStyle
,
tabs:
const
<
Widget
>[
Text
(
'1'
),
Text
(
'2'
)],
),
),
),
);
}
// Returns int `color.value`s instead of Color `color`s to prevent false
// negative due to object types being different (Color != MaterialStateColor)
// when `expect`ing.
int
?
getTab1Color
()
=>
IconTheme
.
of
(
tester
.
element
(
find
.
text
(
'1'
))).
color
?.
value
;
int
?
getTab2Color
()
=>
IconTheme
.
of
(
tester
.
element
(
find
.
text
(
'2'
))).
color
?.
value
;
int
getSelectedColor
(
Color
color
)
=>
(
color
as
MaterialStateColor
)
.
resolve
(<
MaterialState
>{
MaterialState
.
selected
}).
value
;
int
getUnselectedColor
(
Color
color
)
=>
(
color
as
MaterialStateColor
)
.
resolve
(<
MaterialState
>{}).
value
;
// highest precedence: labelColor as MaterialStateColor
await
tester
.
pumpWidget
(
buildTabBar
(
isLabelColorMSC:
true
));
expect
(
getTab1Color
(),
equals
(
getSelectedColor
(
materialLabelColor
)));
expect
(
getTab2Color
(),
equals
(
getUnselectedColor
(
materialLabelColor
)));
// next precedence: labelColor and unselectedLabelColor
await
tester
.
pumpWidget
(
buildTabBar
());
expect
(
getTab1Color
(),
equals
(
labelColor
.
value
));
expect
(
getTab2Color
(),
equals
(
unselectedLabelColor
.
value
));
// next precedence: tabBarTheme.labelColor as MaterialStateColor
await
tester
.
pumpWidget
(
buildTabBar
(
isLabelColorNull:
true
,
isTabBarThemeMSC:
true
,
));
expect
(
getTab1Color
(),
equals
(
getSelectedColor
(
materialTabBarTheme
.
labelColor
!)));
expect
(
getTab2Color
(),
equals
(
getUnselectedColor
(
materialTabBarTheme
.
labelColor
!)));
// next precedence: tabBarTheme.labelColor and
// tabBarTheme.unselectedLabelColor
await
tester
.
pumpWidget
(
buildTabBar
(
isLabelColorNull:
true
,
isUnselectedLabelColorNull:
true
,
));
expect
(
getTab1Color
(),
equals
(
tabBarTheme
.
labelColor
!.
value
));
expect
(
getTab2Color
(),
equals
(
tabBarTheme
.
unselectedLabelColor
!.
value
));
// next precedence: labelColor and labelColor at 70% opacity
await
tester
.
pumpWidget
(
buildTabBar
(
isUnselectedLabelColorNull:
true
,
isTabBarThemeUnselectedLabelColorNull:
true
,
));
expect
(
getTab1Color
(),
equals
(
labelColor
.
value
));
expect
(
getTab2Color
(),
equals
(
labelColor
.
withAlpha
(
0xB2
).
value
));
// next precedence: tabBarTheme.labelColor and tabBarTheme.labelColor at 70%
// opacity
await
tester
.
pumpWidget
(
buildTabBar
(
isLabelColorNull:
true
,
isUnselectedLabelColorNull:
true
,
isTabBarThemeUnselectedLabelColorNull:
true
,
));
expect
(
getTab1Color
(),
equals
(
tabBarThemeWithNullUnselectedLabelColor
.
labelColor
!.
value
));
expect
(
getTab2Color
(),
equals
(
tabBarThemeWithNullUnselectedLabelColor
.
labelColor
!.
withAlpha
(
0xB2
).
value
));
// last precedence: themeData.primaryTextTheme.bodyText1.color and
// themeData.primaryTextTheme.bodyText1.color.withAlpha(0xB2)
await
tester
.
pumpWidget
(
buildTabBar
(
isLabelColorNull:
true
,
isUnselectedLabelColorNull:
true
,
isTabBarThemeNull:
true
,
));
expect
(
getTab1Color
(),
equals
(
ThemeData
().
primaryTextTheme
.
bodyText1
!.
color
!.
value
));
expect
(
getTab2Color
(),
equals
(
ThemeData
().
primaryTextTheme
.
bodyText1
!.
color
!.
withAlpha
(
0xB2
).
value
));
});
testWidgets
(
'Replacing the tabController after disposing the old one'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Replacing the tabController after disposing the old one'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/32428
// Regression test for https://github.com/flutter/flutter/issues/32428
...
@@ -4309,7 +4444,7 @@ void main() {
...
@@ -4309,7 +4444,7 @@ void main() {
expect
(
pageView
.
physics
.
toString
().
contains
(
'ClampingScrollPhysics'
),
isFalse
);
expect
(
pageView
.
physics
.
toString
().
contains
(
'ClampingScrollPhysics'
),
isFalse
);
});
});
testWidgets
(
'TabController
changes offset attribute
'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'TabController
.offset changes reflect labelColor
'
,
(
WidgetTester
tester
)
async
{
final
TabController
controller
=
TabController
(
final
TabController
controller
=
TabController
(
vsync:
const
TestVSync
(),
vsync:
const
TestVSync
(),
length:
2
,
length:
2
,
...
@@ -4318,11 +4453,24 @@ void main() {
...
@@ -4318,11 +4453,24 @@ void main() {
late
Color
firstColor
;
late
Color
firstColor
;
late
Color
secondColor
;
late
Color
secondColor
;
await
tester
.
pumpWidget
(
Widget
buildTabBar
({
bool
labelColorIsMaterialStateColor
=
false
})
{
boilerplate
(
final
Color
labelColor
=
labelColorIsMaterialStateColor
?
MaterialStateColor
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
Colors
.
white
;
}
else
{
// this is a third color to also test if unselectedLabelColor
// is ignored when labelColor is MaterialStateColor
return
Colors
.
transparent
;
}
})
:
Colors
.
white
;
return
boilerplate
(
child:
TabBar
(
child:
TabBar
(
controller:
controller
,
controller:
controller
,
labelColor:
Colors
.
white
,
labelColor:
labelColor
,
unselectedLabelColor:
Colors
.
black
,
unselectedLabelColor:
Colors
.
black
,
tabs:
<
Widget
>[
tabs:
<
Widget
>[
Builder
(
builder:
(
BuildContext
context
)
{
Builder
(
builder:
(
BuildContext
context
)
{
...
@@ -4335,29 +4483,50 @@ void main() {
...
@@ -4335,29 +4483,50 @@ void main() {
}),
}),
],
],
),
),
),
);
);
}
expect
(
firstColor
,
equals
(
Colors
.
white
));
Future
<
void
>
testLabelColor
({
expect
(
secondColor
,
equals
(
Colors
.
black
));
required
Color
selectedColor
,
required
Color
unselectedColor
,
})
async
{
expect
(
firstColor
,
equals
(
selectedColor
));
expect
(
secondColor
,
equals
(
unselectedColor
));
controller
.
offset
=
0.6
;
controller
.
offset
=
0.6
;
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
firstColor
,
equals
(
Color
.
lerp
(
Colors
.
white
,
Colors
.
black
,
0.6
)));
expect
(
firstColor
,
equals
(
Color
.
lerp
(
selectedColor
,
unselectedColor
,
0.6
)));
expect
(
secondColor
,
equals
(
Color
.
lerp
(
Colors
.
black
,
Colors
.
white
,
0.6
)));
expect
(
secondColor
,
equals
(
Color
.
lerp
(
unselectedColor
,
selectedColor
,
0.6
)));
controller
.
index
=
1
;
controller
.
index
=
1
;
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
firstColor
,
equals
(
Colors
.
black
));
expect
(
firstColor
,
equals
(
unselectedColor
));
expect
(
secondColor
,
equals
(
Colors
.
white
));
expect
(
secondColor
,
equals
(
selectedColor
));
controller
.
offset
=
0.6
;
controller
.
offset
=
0.6
;
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
firstColor
,
equals
(
Colors
.
black
));
expect
(
firstColor
,
equals
(
unselectedColor
));
expect
(
secondColor
,
equals
(
Colors
.
white
));
expect
(
secondColor
,
equals
(
selectedColor
));
controller
.
offset
=
-
0.6
;
await
tester
.
pump
();
expect
(
firstColor
,
equals
(
Color
.
lerp
(
selectedColor
,
unselectedColor
,
0.4
)));
expect
(
secondColor
,
equals
(
Color
.
lerp
(
unselectedColor
,
selectedColor
,
0.4
)));
}
await
tester
.
pumpWidget
(
buildTabBar
());
await
testLabelColor
(
selectedColor:
Colors
.
white
,
unselectedColor:
Colors
.
black
);
// reset
controller
.
index
=
0
;
await
tester
.
pump
();
await
tester
.
pumpWidget
(
buildTabBar
(
labelColorIsMaterialStateColor:
true
));
await
testLabelColor
(
selectedColor:
Colors
.
white
,
unselectedColor:
Colors
.
transparent
);
});
});
testWidgets
(
'Crash on dispose'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Crash on dispose'
,
(
WidgetTester
tester
)
async
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment