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
02d5c759
Unverified
Commit
02d5c759
authored
Mar 23, 2023
by
Pierre-Louis
Committed by
GitHub
Mar 23, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for secondary tab bar (#122756)
Add support for secondary tab bar
parent
ce68d979
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
801 additions
and
130 deletions
+801
-130
tabs_template.dart
dev/tools/gen_defaults/lib/tabs_template.dart
+61
-2
tab_bar.0.dart
examples/api/lib/material/tabs/tab_bar.0.dart
+9
-11
tab_bar.1.dart
examples/api/lib/material/tabs/tab_bar.1.dart
+18
-15
tab_bar.2.dart
examples/api/lib/material/tabs/tab_bar.2.dart
+117
-0
tab_bar.0_test.dart
examples/api/test/material/tabs/tab_bar.0_test.dart
+51
-0
tab_bar.1_test.dart
examples/api/test/material/tabs/tab_bar.1_test.dart
+51
-0
tab_bar.2_test.dart
examples/api/test/material/tabs/tab_bar.2_test.dart
+71
-0
tabs.dart
packages/flutter/lib/src/material/tabs.dart
+164
-25
tab_bar_theme_test.dart
packages/flutter/test/material/tab_bar_theme_test.dart
+149
-65
tabs_test.dart
packages/flutter/test/material/tabs_test.dart
+110
-12
No files found.
dev/tools/gen_defaults/lib/tabs_template.dart
View file @
02d5c759
...
@@ -12,8 +12,8 @@ class TabsTemplate extends TokenTemplate {
...
@@ -12,8 +12,8 @@ class TabsTemplate extends TokenTemplate {
@override
@override
String
generate
()
=>
'''
String
generate
()
=>
'''
class _
${blockName}
DefaultsM3 extends TabBarTheme {
class _
${blockName}
Primary
DefaultsM3 extends TabBarTheme {
_
${blockName}
DefaultsM3(this.context)
_
${blockName}
Primary
DefaultsM3(this.context)
: super(indicatorSize: TabBarIndicatorSize.label);
: super(indicatorSize: TabBarIndicatorSize.label);
final BuildContext context;
final BuildContext context;
...
@@ -69,5 +69,64 @@ class _${blockName}DefaultsM3 extends TabBarTheme {
...
@@ -69,5 +69,64 @@ class _${blockName}DefaultsM3 extends TabBarTheme {
@override
@override
InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory;
InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory;
}
}
class _
${blockName}
SecondaryDefaultsM3 extends TabBarTheme {
_
${blockName}
SecondaryDefaultsM3(this.context)
: super(indicatorSize: TabBarIndicatorSize.tab);
final BuildContext context;
late final ColorScheme _colors = Theme.of(context).colorScheme;
late final TextTheme _textTheme = Theme.of(context).textTheme;
@override
Color? get dividerColor =>
${componentColor("md.comp.secondary-navigation-tab.divider")}
;
@override
Color? get indicatorColor =>
${componentColor("md.comp.primary-navigation-tab.active-indicator")}
;
@override
Color? get labelColor =>
${componentColor("md.comp.secondary-navigation-tab.active.label-text")}
;
@override
TextStyle? get labelStyle =>
${textStyle("md.comp.secondary-navigation-tab.label-text")}
;
@override
Color? get unselectedLabelColor =>
${componentColor("md.comp.secondary-navigation-tab.inactive.label-text")}
;
@override
TextStyle? get unselectedLabelStyle =>
${textStyle("md.comp.secondary-navigation-tab.label-text")}
;
@override
MaterialStateProperty<Color?> get overlayColor {
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
if (states.contains(MaterialState.hovered)) {
return
${componentColor('md.comp.secondary-navigation-tab.hover.state-layer')}
;
}
if (states.contains(MaterialState.focused)) {
return
${componentColor('md.comp.secondary-navigation-tab.focus.state-layer')}
;
}
if (states.contains(MaterialState.pressed)) {
return
${componentColor('md.comp.secondary-navigation-tab.pressed.state-layer')}
;
}
return null;
}
if (states.contains(MaterialState.hovered)) {
return
${componentColor('md.comp.secondary-navigation-tab.hover.state-layer')}
;
}
if (states.contains(MaterialState.focused)) {
return
${componentColor('md.comp.secondary-navigation-tab.focus.state-layer')}
;
}
if (states.contains(MaterialState.pressed)) {
return
${componentColor('md.comp.secondary-navigation-tab.pressed.state-layer')}
;
}
return null;
});
}
@override
InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory;
}
'''
;
'''
;
}
}
examples/api/lib/material/tabs/tab_bar.0.dart
View file @
02d5c759
...
@@ -6,24 +6,22 @@
...
@@ -6,24 +6,22 @@
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
void
main
(
)
=>
runApp
(
const
My
App
());
void
main
(
)
=>
runApp
(
const
TabBar
App
());
class
MyApp
extends
StatelessWidget
{
class
TabBarApp
extends
StatelessWidget
{
const
MyApp
({
super
.
key
});
const
TabBarApp
({
super
.
key
});
static
const
String
_title
=
'Flutter Code Sample'
;
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
const
MaterialApp
(
return
MaterialApp
(
t
itle:
_title
,
t
heme:
ThemeData
(
useMaterial3:
true
)
,
home:
MyStatelessWidget
(),
home:
const
TabBarExample
(),
);
);
}
}
}
}
class
MyStatelessWidget
extends
StatelessWidget
{
class
TabBarExample
extends
StatelessWidget
{
const
MyStatelessWidget
({
super
.
key
});
const
TabBarExample
({
super
.
key
});
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
...
@@ -32,7 +30,7 @@ class MyStatelessWidget extends StatelessWidget {
...
@@ -32,7 +30,7 @@ class MyStatelessWidget extends StatelessWidget {
length:
3
,
length:
3
,
child:
Scaffold
(
child:
Scaffold
(
appBar:
AppBar
(
appBar:
AppBar
(
title:
const
Text
(
'TabBar
Widget
'
),
title:
const
Text
(
'TabBar
Sample
'
),
bottom:
const
TabBar
(
bottom:
const
TabBar
(
tabs:
<
Widget
>[
tabs:
<
Widget
>[
Tab
(
Tab
(
...
...
examples/api/lib/material/tabs/tab_bar.1.dart
View file @
02d5c759
...
@@ -6,34 +6,31 @@
...
@@ -6,34 +6,31 @@
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
void
main
(
)
=>
runApp
(
const
My
App
());
void
main
(
)
=>
runApp
(
const
TabBar
App
());
class
MyApp
extends
StatelessWidget
{
class
TabBarApp
extends
StatelessWidget
{
const
MyApp
({
super
.
key
});
const
TabBarApp
({
super
.
key
});
static
const
String
_title
=
'Flutter Code Sample'
;
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
const
MaterialApp
(
return
MaterialApp
(
t
itle:
_title
,
t
heme:
ThemeData
(
useMaterial3:
true
)
,
home:
MyStatefulWidget
(),
home:
const
TabBarExample
(),
);
);
}
}
}
}
class
MyStatefulWidget
extends
StatefulWidget
{
class
TabBarExample
extends
StatefulWidget
{
const
MyStatefulWidget
({
super
.
key
});
const
TabBarExample
({
super
.
key
});
@override
@override
State
<
MyStatefulWidget
>
createState
()
=>
_MyStatefulWidget
State
();
State
<
TabBarExample
>
createState
()
=>
_TabBarExample
State
();
}
}
/// [AnimationController]s can be created with `vsync: this` because of
/// [AnimationController]s can be created with `vsync: this` because of
/// [TickerProviderStateMixin].
/// [TickerProviderStateMixin].
class
_MyStatefulWidgetState
extends
State
<
MyStatefulWidget
>
class
_TabBarExampleState
extends
State
<
TabBarExample
>
with
TickerProviderStateMixin
{
with
TickerProviderStateMixin
{
late
final
TabController
_tabController
;
late
TabController
_tabController
;
@override
@override
void
initState
()
{
void
initState
()
{
...
@@ -41,11 +38,17 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget>
...
@@ -41,11 +38,17 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget>
_tabController
=
TabController
(
length:
3
,
vsync:
this
);
_tabController
=
TabController
(
length:
3
,
vsync:
this
);
}
}
@override
void
dispose
()
{
_tabController
.
dispose
();
super
.
dispose
();
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
return
Scaffold
(
appBar:
AppBar
(
appBar:
AppBar
(
title:
const
Text
(
'TabBar
Widget
'
),
title:
const
Text
(
'TabBar
Sample
'
),
bottom:
TabBar
(
bottom:
TabBar
(
controller:
_tabController
,
controller:
_tabController
,
tabs:
const
<
Widget
>[
tabs:
const
<
Widget
>[
...
...
examples/api/lib/material/tabs/tab_bar.2.dart
0 → 100644
View file @
02d5c759
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flutter code sample for [TabBar].
import
'package:flutter/material.dart'
;
void
main
(
)
=>
runApp
(
const
TabBarApp
());
class
TabBarApp
extends
StatelessWidget
{
const
TabBarApp
({
super
.
key
});
@override
Widget
build
(
BuildContext
context
)
{
return
MaterialApp
(
theme:
ThemeData
(
useMaterial3:
true
),
home:
const
TabBarExample
(),
);
}
}
class
TabBarExample
extends
StatelessWidget
{
const
TabBarExample
({
super
.
key
});
@override
Widget
build
(
BuildContext
context
)
{
return
DefaultTabController
(
initialIndex:
1
,
length:
3
,
child:
Scaffold
(
appBar:
AppBar
(
title:
const
Text
(
'Primary and secondary TabBar'
),
bottom:
const
TabBar
(
dividerColor:
Colors
.
transparent
,
tabs:
<
Widget
>[
Tab
(
text:
'Flights'
,
icon:
Icon
(
Icons
.
flight
),
),
Tab
(
text:
'Trips'
,
icon:
Icon
(
Icons
.
luggage
),
),
Tab
(
text:
'Explore'
,
icon:
Icon
(
Icons
.
explore
),
),
],
),
),
body:
const
TabBarView
(
children:
<
Widget
>[
NestedTabBar
(
'Flights'
),
NestedTabBar
(
'Trips'
),
NestedTabBar
(
'Explore'
),
],
),
),
);
}
}
class
NestedTabBar
extends
StatefulWidget
{
const
NestedTabBar
(
this
.
outerTab
,
{
super
.
key
});
final
String
outerTab
;
@override
State
<
NestedTabBar
>
createState
()
=>
_NestedTabBarState
();
}
class
_NestedTabBarState
extends
State
<
NestedTabBar
>
with
TickerProviderStateMixin
{
late
final
TabController
_tabController
;
@override
void
initState
()
{
super
.
initState
();
_tabController
=
TabController
(
length:
2
,
vsync:
this
);
}
@override
void
dispose
()
{
_tabController
.
dispose
();
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
Column
(
children:
<
Widget
>[
TabBar
.
secondary
(
controller:
_tabController
,
tabs:
const
<
Widget
>[
Tab
(
text:
'Overview'
),
Tab
(
text:
'Specifications'
),
],
),
Expanded
(
child:
TabBarView
(
controller:
_tabController
,
children:
<
Widget
>[
Card
(
margin:
const
EdgeInsets
.
all
(
16.0
),
child:
Center
(
child:
Text
(
'
${widget.outerTab}
: Overview tab'
)),
),
Card
(
margin:
const
EdgeInsets
.
all
(
16.0
),
child:
Center
(
child:
Text
(
'
${widget.outerTab}
: Specifications tab'
)),
),
],
),
),
],
);
}
}
examples/api/test/material/tabs/tab_bar.0_test.dart
0 → 100644
View file @
02d5c759
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/material.dart'
;
import
'package:flutter_api_samples/material/tabs/tab_bar.0.dart'
as
example
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'Switch tabs in the TabBar'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
TabBarApp
(),
);
final
TabBar
tabBar
=
tester
.
widget
<
TabBar
>(
find
.
byType
(
TabBar
));
expect
(
tabBar
.
tabs
.
length
,
3
);
final
Finder
tab1
=
find
.
widgetWithIcon
(
Tab
,
Icons
.
cloud_outlined
);
final
Finder
tab2
=
find
.
widgetWithIcon
(
Tab
,
Icons
.
beach_access_sharp
);
final
Finder
tab3
=
find
.
widgetWithIcon
(
Tab
,
Icons
.
brightness_5_sharp
);
const
String
tabBarViewText1
=
"It's cloudy here"
;
const
String
tabBarViewText2
=
"It's rainy here"
;
const
String
tabBarViewText3
=
"It's sunny here"
;
expect
(
find
.
text
(
tabBarViewText1
),
findsNothing
);
expect
(
find
.
text
(
tabBarViewText2
),
findsOneWidget
);
expect
(
find
.
text
(
tabBarViewText3
),
findsNothing
);
await
tester
.
tap
(
tab1
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tabBarViewText1
),
findsOneWidget
);
expect
(
find
.
text
(
tabBarViewText2
),
findsNothing
);
expect
(
find
.
text
(
tabBarViewText3
),
findsNothing
);
await
tester
.
tap
(
tab2
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tabBarViewText1
),
findsNothing
);
expect
(
find
.
text
(
tabBarViewText2
),
findsOneWidget
);
expect
(
find
.
text
(
tabBarViewText3
),
findsNothing
);
await
tester
.
tap
(
tab3
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tabBarViewText1
),
findsNothing
);
expect
(
find
.
text
(
tabBarViewText2
),
findsNothing
);
expect
(
find
.
text
(
tabBarViewText3
),
findsOneWidget
);
});
}
examples/api/test/material/tabs/tab_bar.1_test.dart
0 → 100644
View file @
02d5c759
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/material.dart'
;
import
'package:flutter_api_samples/material/tabs/tab_bar.1.dart'
as
example
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'Switch tabs in the TabBar'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
TabBarApp
(),
);
final
TabBar
tabBar
=
tester
.
widget
<
TabBar
>(
find
.
byType
(
TabBar
));
expect
(
tabBar
.
tabs
.
length
,
3
);
final
Finder
tab1
=
find
.
widgetWithIcon
(
Tab
,
Icons
.
cloud_outlined
);
final
Finder
tab2
=
find
.
widgetWithIcon
(
Tab
,
Icons
.
beach_access_sharp
);
final
Finder
tab3
=
find
.
widgetWithIcon
(
Tab
,
Icons
.
brightness_5_sharp
);
const
String
tabBarViewText1
=
"It's cloudy here"
;
const
String
tabBarViewText2
=
"It's rainy here"
;
const
String
tabBarViewText3
=
"It's sunny here"
;
expect
(
find
.
text
(
tabBarViewText1
),
findsOneWidget
);
expect
(
find
.
text
(
tabBarViewText2
),
findsNothing
);
expect
(
find
.
text
(
tabBarViewText3
),
findsNothing
);
await
tester
.
tap
(
tab1
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tabBarViewText1
),
findsOneWidget
);
expect
(
find
.
text
(
tabBarViewText2
),
findsNothing
);
expect
(
find
.
text
(
tabBarViewText3
),
findsNothing
);
await
tester
.
tap
(
tab2
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tabBarViewText1
),
findsNothing
);
expect
(
find
.
text
(
tabBarViewText2
),
findsOneWidget
);
expect
(
find
.
text
(
tabBarViewText3
),
findsNothing
);
await
tester
.
tap
(
tab3
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tabBarViewText1
),
findsNothing
);
expect
(
find
.
text
(
tabBarViewText2
),
findsNothing
);
expect
(
find
.
text
(
tabBarViewText3
),
findsOneWidget
);
});
}
examples/api/test/material/tabs/tab_bar.2_test.dart
0 → 100644
View file @
02d5c759
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/material.dart'
;
import
'package:flutter_api_samples/material/tabs/tab_bar.2.dart'
as
example
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'Switch tabs in the TabBar'
,
(
WidgetTester
tester
)
async
{
const
String
primaryTabLabel1
=
'Flights'
;
const
String
primaryTabLabel2
=
'Trips'
;
const
String
primaryTabLabel3
=
'Explore'
;
const
String
secondaryTabLabel1
=
'Overview'
;
const
String
secondaryTabLabel2
=
'Specifications'
;
await
tester
.
pumpWidget
(
const
example
.
TabBarApp
(),
);
final
TabBar
primaryTabBar
=
tester
.
widget
<
TabBar
>(
find
.
byType
(
TabBar
).
last
);
expect
(
primaryTabBar
.
tabs
.
length
,
3
);
final
TabBar
secondaryTabBar
=
tester
.
widget
<
TabBar
>(
find
.
byType
(
TabBar
).
first
);
expect
(
secondaryTabBar
.
tabs
.
length
,
2
);
final
Finder
primaryTab1
=
find
.
widgetWithText
(
Tab
,
primaryTabLabel1
);
final
Finder
primaryTab2
=
find
.
widgetWithText
(
Tab
,
primaryTabLabel2
);
final
Finder
primaryTab3
=
find
.
widgetWithText
(
Tab
,
primaryTabLabel3
);
final
Finder
secondaryTab2
=
find
.
widgetWithText
(
Tab
,
secondaryTabLabel2
);
String
tabBarViewText
=
'
$primaryTabLabel2
:
$secondaryTabLabel1
tab'
;
expect
(
find
.
text
(
tabBarViewText
),
findsOneWidget
);
await
tester
.
tap
(
primaryTab1
);
await
tester
.
pumpAndSettle
();
tabBarViewText
=
'
$primaryTabLabel1
:
$secondaryTabLabel1
tab'
;
expect
(
find
.
text
(
tabBarViewText
),
findsOneWidget
);
await
tester
.
tap
(
secondaryTab2
);
await
tester
.
pumpAndSettle
();
tabBarViewText
=
'
$primaryTabLabel1
:
$secondaryTabLabel2
tab'
;
expect
(
find
.
text
(
tabBarViewText
),
findsOneWidget
);
await
tester
.
tap
(
primaryTab2
);
await
tester
.
pumpAndSettle
();
tabBarViewText
=
'
$primaryTabLabel2
:
$secondaryTabLabel1
tab'
;
expect
(
find
.
text
(
tabBarViewText
),
findsOneWidget
);
await
tester
.
tap
(
secondaryTab2
);
await
tester
.
pumpAndSettle
();
tabBarViewText
=
'
$primaryTabLabel2
:
$secondaryTabLabel2
tab'
;
expect
(
find
.
text
(
tabBarViewText
),
findsOneWidget
);
await
tester
.
tap
(
primaryTab3
);
await
tester
.
pumpAndSettle
();
tabBarViewText
=
'
$primaryTabLabel3
:
$secondaryTabLabel1
tab'
;
expect
(
find
.
text
(
tabBarViewText
),
findsOneWidget
);
await
tester
.
tap
(
secondaryTab2
);
await
tester
.
pumpAndSettle
();
tabBarViewText
=
'
$primaryTabLabel3
:
$secondaryTabLabel2
tab'
;
expect
(
find
.
text
(
tabBarViewText
),
findsOneWidget
);
});
}
packages/flutter/lib/src/material/tabs.dart
View file @
02d5c759
This diff is collapsed.
Click to expand it.
packages/flutter/test/material/tab_bar_theme_test.dart
View file @
02d5c759
This diff is collapsed.
Click to expand it.
packages/flutter/test/material/tabs_test.dart
View file @
02d5c759
...
@@ -106,6 +106,7 @@ class _NestedTabBarContainer extends StatelessWidget {
...
@@ -106,6 +106,7 @@ class _NestedTabBarContainer extends StatelessWidget {
Widget
buildFrame
(
{
Widget
buildFrame
(
{
Key
?
tabBarKey
,
Key
?
tabBarKey
,
bool
secondaryTabBar
=
false
,
required
List
<
String
>
tabs
,
required
List
<
String
>
tabs
,
required
String
value
,
required
String
value
,
bool
isScrollable
=
false
,
bool
isScrollable
=
false
,
...
@@ -114,6 +115,24 @@ Widget buildFrame({
...
@@ -114,6 +115,24 @@ Widget buildFrame({
EdgeInsetsGeometry
?
padding
,
EdgeInsetsGeometry
?
padding
,
TextDirection
textDirection
=
TextDirection
.
ltr
,
TextDirection
textDirection
=
TextDirection
.
ltr
,
})
{
})
{
if
(
secondaryTabBar
)
{
return
boilerplate
(
textDirection:
textDirection
,
child:
DefaultTabController
(
animationDuration:
animationDuration
,
initialIndex:
tabs
.
indexOf
(
value
),
length:
tabs
.
length
,
child:
TabBar
.
secondary
(
key:
tabBarKey
,
tabs:
tabs
.
map
<
Widget
>((
String
tab
)
=>
Tab
(
text:
tab
)).
toList
(),
isScrollable:
isScrollable
,
indicatorColor:
indicatorColor
,
padding:
padding
,
),
),
);
}
return
boilerplate
(
return
boilerplate
(
textDirection:
textDirection
,
textDirection:
textDirection
,
child:
DefaultTabController
(
child:
DefaultTabController
(
...
@@ -238,6 +257,10 @@ class TestScrollPhysics extends ScrollPhysics {
...
@@ -238,6 +257,10 @@ class TestScrollPhysics extends ScrollPhysics {
SpringDescription
get
spring
=>
_kDefaultSpring
;
SpringDescription
get
spring
=>
_kDefaultSpring
;
}
}
RenderParagraph
_getText
(
WidgetTester
tester
,
String
text
)
{
return
tester
.
renderObject
<
RenderParagraph
>(
find
.
text
(
text
));
}
void
main
(
)
{
void
main
(
)
{
setUp
(()
{
setUp
(()
{
debugResetSemanticsIdCounter
();
debugResetSemanticsIdCounter
();
...
@@ -358,12 +381,12 @@ void main() {
...
@@ -358,12 +381,12 @@ void main() {
expect
(
find
.
byType
(
TabBar
),
paints
..
line
(
color:
Colors
.
blue
[
500
]));
expect
(
find
.
byType
(
TabBar
),
paints
..
line
(
color:
Colors
.
blue
[
500
]));
});
});
testWidgets
(
'TabBar default selected/unselected
text style
'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'TabBar default selected/unselected
label style (primary)
'
,
(
WidgetTester
tester
)
async
{
final
ThemeData
theme
=
ThemeData
(
useMaterial3:
true
);
final
ThemeData
theme
=
ThemeData
(
useMaterial3:
true
);
final
List
<
String
>
tabs
=
<
String
>[
'A'
,
'B'
,
'C'
];
final
List
<
String
>
tabs
=
<
String
>[
'A'
,
'B'
,
'C'
];
const
String
selectedValue
=
'A'
;
const
String
selectedValue
=
'A'
;
const
String
un
S
electedValue
=
'C'
;
const
String
un
s
electedValue
=
'C'
;
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Theme
(
Theme
(
data:
theme
,
data:
theme
,
...
@@ -375,20 +398,95 @@ void main() {
...
@@ -375,20 +398,95 @@ void main() {
expect
(
find
.
text
(
'C'
),
findsOneWidget
);
expect
(
find
.
text
(
'C'
),
findsOneWidget
);
// Test selected label text style.
// Test selected label text style.
expect
(
tester
.
renderObject
<
RenderParagraph
>(
find
.
text
(
selectedValue
)).
text
.
style
!.
fontFamily
,
'Roboto'
);
final
RenderParagraph
selectedLabel
=
_getText
(
tester
,
selectedValue
);
expect
(
tester
.
renderObject
<
RenderParagraph
>(
find
.
text
(
selectedValue
)).
text
.
style
!.
fontSize
,
14.0
);
expect
(
selectedLabel
.
text
.
style
!.
fontFamily
,
'Roboto'
);
expect
(
tester
.
renderObject
<
RenderParagraph
>(
expect
(
selectedLabel
.
text
.
style
!.
fontSize
,
14.0
);
find
.
text
(
selectedValue
)).
text
.
style
!.
color
,
expect
(
selectedLabel
.
text
.
style
!.
color
,
theme
.
colorScheme
.
primary
);
theme
.
colorScheme
.
primary
,
// Test unselected label text style.
final
RenderParagraph
unselectedLabel
=
_getText
(
tester
,
unselectedValue
);
expect
(
unselectedLabel
.
text
.
style
!.
fontFamily
,
'Roboto'
);
expect
(
unselectedLabel
.
text
.
style
!.
fontSize
,
14.0
);
expect
(
unselectedLabel
.
text
.
style
!.
color
,
theme
.
colorScheme
.
onSurfaceVariant
);
});
testWidgets
(
'TabBar default selected/unselected label style (secondary)'
,
(
WidgetTester
tester
)
async
{
final
ThemeData
theme
=
ThemeData
(
useMaterial3:
true
);
final
List
<
String
>
tabs
=
<
String
>[
'A'
,
'B'
,
'C'
];
const
String
selectedValue
=
'A'
;
const
String
unselectedValue
=
'C'
;
await
tester
.
pumpWidget
(
Theme
(
data:
theme
,
child:
buildFrame
(
tabs:
tabs
,
value:
selectedValue
,
secondaryTabBar:
true
),
),
);
);
expect
(
find
.
text
(
'A'
),
findsOneWidget
);
expect
(
find
.
text
(
'B'
),
findsOneWidget
);
expect
(
find
.
text
(
'C'
),
findsOneWidget
);
// Test selected label text style.
final
RenderParagraph
selectedLabel
=
_getText
(
tester
,
selectedValue
);
expect
(
selectedLabel
.
text
.
style
!.
fontFamily
,
'Roboto'
);
expect
(
selectedLabel
.
text
.
style
!.
fontSize
,
14.0
);
expect
(
selectedLabel
.
text
.
style
!.
color
,
theme
.
colorScheme
.
onSurface
);
// Test unselected label text style.
// Test unselected label text style.
expect
(
tester
.
renderObject
<
RenderParagraph
>(
find
.
text
(
unSelectedValue
)).
text
.
style
!.
fontFamily
,
'Roboto'
);
final
RenderParagraph
unselectedLabel
=
_getText
(
tester
,
unselectedValue
);
expect
(
tester
.
renderObject
<
RenderParagraph
>(
find
.
text
(
unSelectedValue
)).
text
.
style
!.
fontSize
,
14.0
);
expect
(
unselectedLabel
.
text
.
style
!.
fontFamily
,
'Roboto'
);
expect
(
tester
.
renderObject
<
RenderParagraph
>(
expect
(
unselectedLabel
.
text
.
style
!.
fontSize
,
14.0
);
find
.
text
(
unSelectedValue
)).
text
.
style
!.
color
,
expect
(
unselectedLabel
.
text
.
style
!.
color
,
theme
.
colorScheme
.
onSurfaceVariant
);
theme
.
colorScheme
.
onSurfaceVariant
,
});
testWidgets
(
'TabBar default overlay (primary)'
,
(
WidgetTester
tester
)
async
{
final
ThemeData
theme
=
ThemeData
(
useMaterial3:
true
);
final
List
<
String
>
tabs
=
<
String
>[
'A'
,
'B'
];
const
String
selectedValue
=
'A'
;
const
String
unselectedValue
=
'B'
;
await
tester
.
pumpWidget
(
Theme
(
data:
theme
,
child:
buildFrame
(
tabs:
tabs
,
value:
selectedValue
),
),
);
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
PointerDeviceKind
.
mouse
);
await
gesture
.
addPointer
();
await
gesture
.
moveTo
(
tester
.
getCenter
(
find
.
text
(
selectedValue
)));
await
tester
.
pumpAndSettle
();
final
RenderObject
inkFeatures
=
tester
.
allRenderObjects
.
firstWhere
((
RenderObject
object
)
=>
object
.
runtimeType
.
toString
()
==
'_RenderInkFeatures'
);
expect
(
inkFeatures
,
paints
..
rect
(
color:
theme
.
colorScheme
.
primary
.
withOpacity
(
0.08
)));
await
gesture
.
moveTo
(
tester
.
getCenter
(
find
.
text
(
unselectedValue
)));
await
tester
.
pumpAndSettle
();
expect
(
inkFeatures
,
paints
..
rect
(
color:
theme
.
colorScheme
.
onSurface
.
withOpacity
(
0.08
)));
});
testWidgets
(
'TabBar default overlay (secondary)'
,
(
WidgetTester
tester
)
async
{
final
ThemeData
theme
=
ThemeData
(
useMaterial3:
true
);
final
List
<
String
>
tabs
=
<
String
>[
'A'
,
'B'
];
const
String
selectedValue
=
'A'
;
const
String
unselectedValue
=
'B'
;
await
tester
.
pumpWidget
(
Theme
(
data:
theme
,
child:
buildFrame
(
tabs:
tabs
,
value:
selectedValue
,
secondaryTabBar:
true
),
),
);
);
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
PointerDeviceKind
.
mouse
);
await
gesture
.
addPointer
();
await
gesture
.
moveTo
(
tester
.
getCenter
(
find
.
text
(
selectedValue
)));
await
tester
.
pumpAndSettle
();
final
RenderObject
inkFeatures
=
tester
.
allRenderObjects
.
firstWhere
((
RenderObject
object
)
=>
object
.
runtimeType
.
toString
()
==
'_RenderInkFeatures'
);
expect
(
inkFeatures
,
paints
..
rect
(
color:
theme
.
colorScheme
.
onSurface
.
withOpacity
(
0.08
)));
await
gesture
.
moveTo
(
tester
.
getCenter
(
find
.
text
(
unselectedValue
)));
await
tester
.
pumpAndSettle
();
expect
(
inkFeatures
,
paints
..
rect
(
color:
theme
.
colorScheme
.
onSurface
.
withOpacity
(
0.08
)));
});
});
testWidgets
(
'TabBar tap selects tab'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'TabBar tap selects tab'
,
(
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