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
bd77118e
Unverified
Commit
bd77118e
authored
Dec 01, 2021
by
MH Johnson
Committed by
GitHub
Dec 01, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Material 3] Add optional indicator to Navigation Rail. (#92930)
parent
7ef52267
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
377 additions
and
13 deletions
+377
-13
navigation_bar.dart
packages/flutter/lib/src/material/navigation_bar.dart
+27
-8
navigation_rail.dart
packages/flutter/lib/src/material/navigation_rail.dart
+107
-3
navigation_rail_theme.dart
packages/flutter/lib/src/material/navigation_rail_theme.dart
+23
-1
navigation_rail_test.dart
packages/flutter/test/material/navigation_rail_test.dart
+191
-0
navigation_rail_theme_test.dart
...ges/flutter/test/material/navigation_rail_theme_test.dart
+29
-1
No files found.
packages/flutter/lib/src/material/navigation_bar.dart
View file @
bd77118e
...
@@ -300,7 +300,7 @@ class NavigationDestination extends StatelessWidget {
...
@@ -300,7 +300,7 @@ class NavigationDestination extends StatelessWidget {
return
Stack
(
return
Stack
(
alignment:
Alignment
.
center
,
alignment:
Alignment
.
center
,
children:
<
Widget
>[
children:
<
Widget
>[
_
NavigationIndicator
(
NavigationIndicator
(
animation:
animation
,
animation:
animation
,
color:
navigationBarTheme
.
indicatorColor
,
color:
navigationBarTheme
.
indicatorColor
,
),
),
...
@@ -507,20 +507,24 @@ class _NavigationDestinationInfo extends InheritedWidget {
...
@@ -507,20 +507,24 @@ class _NavigationDestinationInfo extends InheritedWidget {
}
}
}
}
/// Selection Indicator for the Material 3 Navigation Bar component.
/// Selection Indicator for the Material 3 [NavigationBar] and [NavigationRail]
/// components.
///
///
/// When [animation] is 0, the indicator is not present. As [animation] grows
/// When [animation] is 0, the indicator is not present. As [animation] grows
/// from 0 to 1, the indicator scales in on the x axis.
/// from 0 to 1, the indicator scales in on the x axis.
///
///
/// Use
ful
in a [Stack] widget behind the icons in the Material 3 Navigation Bar
/// Use
d
in a [Stack] widget behind the icons in the Material 3 Navigation Bar
/// to illuminate the selected destination.
/// to illuminate the selected destination.
class
_
NavigationIndicator
extends
StatelessWidget
{
class
NavigationIndicator
extends
StatelessWidget
{
/// Builds an indicator, usually used in a stack behind the icon of a
/// Builds an indicator, usually used in a stack behind the icon of a
/// navigation bar destination.
/// navigation bar destination.
const
_
NavigationIndicator
({
const
NavigationIndicator
({
Key
?
key
,
Key
?
key
,
required
this
.
animation
,
required
this
.
animation
,
this
.
color
,
this
.
color
,
this
.
width
=
64
,
this
.
height
=
32
,
this
.
borderRadius
=
const
BorderRadius
.
all
(
Radius
.
circular
(
16
)),
})
:
super
(
key:
key
);
})
:
super
(
key:
key
);
/// Determines the scale of the indicator.
/// Determines the scale of the indicator.
...
@@ -534,6 +538,21 @@ class _NavigationIndicator extends StatelessWidget {
...
@@ -534,6 +538,21 @@ class _NavigationIndicator extends StatelessWidget {
/// If null, defaults to [ColorScheme.secondary].
/// If null, defaults to [ColorScheme.secondary].
final
Color
?
color
;
final
Color
?
color
;
/// The width of the container that holds in the indicator.
///
/// Defaults to `64`.
final
double
width
;
/// The height of the container that holds in the indicator.
///
/// Defaults to `32`.
final
double
height
;
/// The radius of the container that holds in the indicator.
///
/// Defaults to `BorderRadius.circular(16)`.
final
BorderRadius
borderRadius
;
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
ColorScheme
colorScheme
=
Theme
.
of
(
context
).
colorScheme
;
final
ColorScheme
colorScheme
=
Theme
.
of
(
context
).
colorScheme
;
...
@@ -573,10 +592,10 @@ class _NavigationIndicator extends StatelessWidget {
...
@@ -573,10 +592,10 @@ class _NavigationIndicator extends StatelessWidget {
return
FadeTransition
(
return
FadeTransition
(
opacity:
fadeAnimation
,
opacity:
fadeAnimation
,
child:
Container
(
child:
Container
(
width:
64.0
,
width:
width
,
height:
32.0
,
height:
height
,
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
borderRadius:
const
BorderRadius
.
all
(
Radius
.
circular
(
16.0
))
,
borderRadius:
borderRadius
,
color:
color
??
colorScheme
.
secondary
.
withOpacity
(.
24
),
color:
color
??
colorScheme
.
secondary
.
withOpacity
(.
24
),
),
),
),
),
...
...
packages/flutter/lib/src/material/navigation_rail.dart
View file @
bd77118e
...
@@ -10,6 +10,7 @@ import 'color_scheme.dart';
...
@@ -10,6 +10,7 @@ import 'color_scheme.dart';
import
'ink_well.dart'
;
import
'ink_well.dart'
;
import
'material.dart'
;
import
'material.dart'
;
import
'material_localizations.dart'
;
import
'material_localizations.dart'
;
import
'navigation_bar.dart'
;
import
'navigation_rail_theme.dart'
;
import
'navigation_rail_theme.dart'
;
import
'theme.dart'
;
import
'theme.dart'
;
...
@@ -94,6 +95,8 @@ class NavigationRail extends StatefulWidget {
...
@@ -94,6 +95,8 @@ class NavigationRail extends StatefulWidget {
this
.
selectedIconTheme
,
this
.
selectedIconTheme
,
this
.
minWidth
,
this
.
minWidth
,
this
.
minExtendedWidth
,
this
.
minExtendedWidth
,
this
.
useIndicator
,
this
.
indicatorColor
,
})
:
assert
(
destinations
!=
null
&&
destinations
.
length
>=
2
),
})
:
assert
(
destinations
!=
null
&&
destinations
.
length
>=
2
),
assert
(
selectedIndex
!=
null
),
assert
(
selectedIndex
!=
null
),
assert
(
0
<=
selectedIndex
&&
selectedIndex
<
destinations
.
length
),
assert
(
0
<=
selectedIndex
&&
selectedIndex
<
destinations
.
length
),
...
@@ -279,6 +282,21 @@ class NavigationRail extends StatefulWidget {
...
@@ -279,6 +282,21 @@ class NavigationRail extends StatefulWidget {
/// The default value is 256.
/// The default value is 256.
final
double
?
minExtendedWidth
;
final
double
?
minExtendedWidth
;
/// If `true`, adds a rounded [NavigationIndicator] behind the selected
/// destination's icon.
///
/// The indicator's shape will be circular if [labelType] is
/// [NavigationRailLabelType.none], or a [StadiumBorder] if [labelType] is
/// [NavigationRailLabelType.all] or [NavigationRailLabelType.selected].
///
/// If `null`, defaults to [NavigationRailThemeData.useIndicator]. If that is
/// `null`, defaults to [ThemeData.useMaterial3].
final
bool
?
useIndicator
;
/// Overrides the default value of [NavigationRail]'s selection indicator color,
/// when [useIndicator] is true.
final
Color
?
indicatorColor
;
/// Returns the animation that controls the [NavigationRail.extended] state.
/// Returns the animation that controls the [NavigationRail.extended] state.
///
///
/// This can be used to synchronize animations in the [leading] or [trailing]
/// This can be used to synchronize animations in the [leading] or [trailing]
...
@@ -413,6 +431,8 @@ class _NavigationRailState extends State<NavigationRail> with TickerProviderStat
...
@@ -413,6 +431,8 @@ class _NavigationRailState extends State<NavigationRail> with TickerProviderStat
iconTheme:
widget
.
selectedIndex
==
i
?
selectedIconTheme
:
unselectedIconTheme
,
iconTheme:
widget
.
selectedIndex
==
i
?
selectedIconTheme
:
unselectedIconTheme
,
labelTextStyle:
widget
.
selectedIndex
==
i
?
selectedLabelTextStyle
:
unselectedLabelTextStyle
,
labelTextStyle:
widget
.
selectedIndex
==
i
?
selectedLabelTextStyle
:
unselectedLabelTextStyle
,
padding:
widget
.
destinations
[
i
].
padding
,
padding:
widget
.
destinations
[
i
].
padding
,
useIndicator:
widget
.
useIndicator
??
navigationRailTheme
.
useIndicator
??
theme
.
useMaterial3
,
indicatorColor:
widget
.
indicatorColor
??
navigationRailTheme
.
indicatorColor
,
onTap:
()
{
onTap:
()
{
if
(
widget
.
onDestinationSelected
!=
null
)
if
(
widget
.
onDestinationSelected
!=
null
)
widget
.
onDestinationSelected
!(
i
);
widget
.
onDestinationSelected
!(
i
);
...
@@ -498,6 +518,8 @@ class _RailDestination extends StatelessWidget {
...
@@ -498,6 +518,8 @@ class _RailDestination extends StatelessWidget {
required
this
.
onTap
,
required
this
.
onTap
,
required
this
.
indexLabel
,
required
this
.
indexLabel
,
this
.
padding
,
this
.
padding
,
required
this
.
useIndicator
,
this
.
indicatorColor
,
})
:
assert
(
minWidth
!=
null
),
})
:
assert
(
minWidth
!=
null
),
assert
(
minExtendedWidth
!=
null
),
assert
(
minExtendedWidth
!=
null
),
assert
(
icon
!=
null
),
assert
(
icon
!=
null
),
...
@@ -529,11 +551,18 @@ class _RailDestination extends StatelessWidget {
...
@@ -529,11 +551,18 @@ class _RailDestination extends StatelessWidget {
final
VoidCallback
onTap
;
final
VoidCallback
onTap
;
final
String
indexLabel
;
final
String
indexLabel
;
final
EdgeInsetsGeometry
?
padding
;
final
EdgeInsetsGeometry
?
padding
;
final
bool
useIndicator
;
final
Color
?
indicatorColor
;
final
Animation
<
double
>
_positionAnimation
;
final
Animation
<
double
>
_positionAnimation
;
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
assert
(
useIndicator
||
indicatorColor
==
null
,
'[NavigationRail.indicatorColor] does not have an effect when [NavigationRail.useIndicator] is false'
,
);
final
Widget
themedIcon
=
IconTheme
(
final
Widget
themedIcon
=
IconTheme
(
data:
iconTheme
,
data:
iconTheme
,
child:
icon
,
child:
icon
,
...
@@ -542,13 +571,19 @@ class _RailDestination extends StatelessWidget {
...
@@ -542,13 +571,19 @@ class _RailDestination extends StatelessWidget {
style:
labelTextStyle
,
style:
labelTextStyle
,
child:
label
,
child:
label
,
);
);
final
Widget
content
;
final
Widget
content
;
switch
(
labelType
)
{
switch
(
labelType
)
{
case
NavigationRailLabelType
.
none
:
case
NavigationRailLabelType
.
none
:
final
Widget
iconPart
=
SizedBox
(
final
Widget
iconPart
=
SizedBox
(
width:
minWidth
,
width:
minWidth
,
height:
minWidth
,
height:
minWidth
,
child:
Align
(
child:
_AddIndicator
(
addIndicator:
useIndicator
,
indicatorColor:
indicatorColor
,
isCircular:
true
,
indicatorAnimation:
destinationAnimation
,
child:
themedIcon
,
child:
themedIcon
,
),
),
);
);
...
@@ -606,6 +641,7 @@ class _RailDestination extends StatelessWidget {
...
@@ -606,6 +641,7 @@ class _RailDestination extends StatelessWidget {
final
double
verticalPadding
=
lerpDouble
(
_verticalDestinationPaddingNoLabel
,
_verticalDestinationPaddingWithLabel
,
appearingAnimationValue
)!;
final
double
verticalPadding
=
lerpDouble
(
_verticalDestinationPaddingNoLabel
,
_verticalDestinationPaddingWithLabel
,
appearingAnimationValue
)!;
final
Interval
interval
=
selected
?
const
Interval
(
0.25
,
0.75
)
:
const
Interval
(
0.75
,
1.0
);
final
Interval
interval
=
selected
?
const
Interval
(
0.25
,
0.75
)
:
const
Interval
(
0.75
,
1.0
);
final
Animation
<
double
>
labelFadeAnimation
=
destinationAnimation
.
drive
(
CurveTween
(
curve:
interval
));
final
Animation
<
double
>
labelFadeAnimation
=
destinationAnimation
.
drive
(
CurveTween
(
curve:
interval
));
content
=
Container
(
content
=
Container
(
constraints:
BoxConstraints
(
constraints:
BoxConstraints
(
minWidth:
minWidth
,
minWidth:
minWidth
,
...
@@ -618,7 +654,13 @@ class _RailDestination extends StatelessWidget {
...
@@ -618,7 +654,13 @@ class _RailDestination extends StatelessWidget {
mainAxisAlignment:
MainAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
<
Widget
>[
children:
<
Widget
>[
SizedBox
(
height:
verticalPadding
),
SizedBox
(
height:
verticalPadding
),
themedIcon
,
_AddIndicator
(
addIndicator:
useIndicator
,
indicatorColor:
indicatorColor
,
isCircular:
false
,
indicatorAnimation:
destinationAnimation
,
child:
themedIcon
,
),
Align
(
Align
(
alignment:
Alignment
.
topCenter
,
alignment:
Alignment
.
topCenter
,
heightFactor:
appearingAnimationValue
,
heightFactor:
appearingAnimationValue
,
...
@@ -645,7 +687,13 @@ class _RailDestination extends StatelessWidget {
...
@@ -645,7 +687,13 @@ class _RailDestination extends StatelessWidget {
child:
Column
(
child:
Column
(
children:
<
Widget
>[
children:
<
Widget
>[
const
SizedBox
(
height:
_verticalDestinationPaddingWithLabel
),
const
SizedBox
(
height:
_verticalDestinationPaddingWithLabel
),
themedIcon
,
_AddIndicator
(
addIndicator:
useIndicator
,
indicatorColor:
indicatorColor
,
isCircular:
false
,
indicatorAnimation:
destinationAnimation
,
child:
themedIcon
,
),
styledLabel
,
styledLabel
,
const
SizedBox
(
height:
_verticalDestinationPaddingWithLabel
),
const
SizedBox
(
height:
_verticalDestinationPaddingWithLabel
),
],
],
...
@@ -682,6 +730,62 @@ class _RailDestination extends StatelessWidget {
...
@@ -682,6 +730,62 @@ class _RailDestination extends StatelessWidget {
}
}
}
}
/// When [addIndicator] is `true`, puts [child] center aligned in a [Stack] with
/// a [NavigationIndicator] behind it, otherwise returns [child].
///
/// When [isCircular] is true, the indicator will be a circle, otherwise the
/// indicator will be a stadium shape.
class
_AddIndicator
extends
StatelessWidget
{
const
_AddIndicator
({
Key
?
key
,
required
this
.
addIndicator
,
required
this
.
isCircular
,
required
this
.
indicatorColor
,
required
this
.
indicatorAnimation
,
required
this
.
child
,
})
:
super
(
key:
key
);
final
bool
addIndicator
;
final
bool
isCircular
;
final
Color
?
indicatorColor
;
final
Animation
<
double
>
indicatorAnimation
;
final
Widget
child
;
@override
Widget
build
(
BuildContext
context
)
{
if
(!
addIndicator
)
{
return
child
;
}
late
final
Widget
indicator
;
if
(
isCircular
)
{
const
double
circularIndicatorDiameter
=
56
;
indicator
=
NavigationIndicator
(
animation:
indicatorAnimation
,
height:
circularIndicatorDiameter
,
width:
circularIndicatorDiameter
,
borderRadius:
BorderRadius
.
circular
(
circularIndicatorDiameter
/
2
),
color:
indicatorColor
,
);
}
else
{
indicator
=
NavigationIndicator
(
animation:
indicatorAnimation
,
width:
56
,
borderRadius:
BorderRadius
.
circular
(
16
),
color:
indicatorColor
,
);
}
return
Stack
(
alignment:
Alignment
.
center
,
children:
<
Widget
>[
indicator
,
child
,
],
);
}
}
/// Defines the behavior of the labels of a [NavigationRail].
/// Defines the behavior of the labels of a [NavigationRail].
///
///
/// See also:
/// See also:
...
...
packages/flutter/lib/src/material/navigation_rail_theme.dart
View file @
bd77118e
...
@@ -44,6 +44,8 @@ class NavigationRailThemeData with Diagnosticable {
...
@@ -44,6 +44,8 @@ class NavigationRailThemeData with Diagnosticable {
this
.
selectedIconTheme
,
this
.
selectedIconTheme
,
this
.
groupAlignment
,
this
.
groupAlignment
,
this
.
labelType
,
this
.
labelType
,
this
.
useIndicator
,
this
.
indicatorColor
,
});
});
/// Color to be used for the [NavigationRail]'s background.
/// Color to be used for the [NavigationRail]'s background.
...
@@ -76,6 +78,14 @@ class NavigationRailThemeData with Diagnosticable {
...
@@ -76,6 +78,14 @@ class NavigationRailThemeData with Diagnosticable {
/// [NavigationRail].
/// [NavigationRail].
final
NavigationRailLabelType
?
labelType
;
final
NavigationRailLabelType
?
labelType
;
/// Whether or not the selected [NavigationRailDestination] should include a
/// [NavigationIndicator].
final
bool
?
useIndicator
;
/// Overrides the default value of [NavigationRail]'s selection indicator color,
/// when [useIndicator] is true.
final
Color
?
indicatorColor
;
/// Creates a copy of this object with the given fields replaced with the
/// Creates a copy of this object with the given fields replaced with the
/// new values.
/// new values.
NavigationRailThemeData
copyWith
({
NavigationRailThemeData
copyWith
({
...
@@ -87,6 +97,8 @@ class NavigationRailThemeData with Diagnosticable {
...
@@ -87,6 +97,8 @@ class NavigationRailThemeData with Diagnosticable {
IconThemeData
?
selectedIconTheme
,
IconThemeData
?
selectedIconTheme
,
double
?
groupAlignment
,
double
?
groupAlignment
,
NavigationRailLabelType
?
labelType
,
NavigationRailLabelType
?
labelType
,
bool
?
useIndicator
,
Color
?
indicatorColor
,
})
{
})
{
return
NavigationRailThemeData
(
return
NavigationRailThemeData
(
backgroundColor:
backgroundColor
??
this
.
backgroundColor
,
backgroundColor:
backgroundColor
??
this
.
backgroundColor
,
...
@@ -97,6 +109,8 @@ class NavigationRailThemeData with Diagnosticable {
...
@@ -97,6 +109,8 @@ class NavigationRailThemeData with Diagnosticable {
selectedIconTheme:
selectedIconTheme
??
this
.
selectedIconTheme
,
selectedIconTheme:
selectedIconTheme
??
this
.
selectedIconTheme
,
groupAlignment:
groupAlignment
??
this
.
groupAlignment
,
groupAlignment:
groupAlignment
??
this
.
groupAlignment
,
labelType:
labelType
??
this
.
labelType
,
labelType:
labelType
??
this
.
labelType
,
useIndicator:
useIndicator
??
this
.
useIndicator
,
indicatorColor:
indicatorColor
??
this
.
indicatorColor
,
);
);
}
}
...
@@ -118,6 +132,8 @@ class NavigationRailThemeData with Diagnosticable {
...
@@ -118,6 +132,8 @@ class NavigationRailThemeData with Diagnosticable {
selectedIconTheme:
IconThemeData
.
lerp
(
a
?.
selectedIconTheme
,
b
?.
selectedIconTheme
,
t
),
selectedIconTheme:
IconThemeData
.
lerp
(
a
?.
selectedIconTheme
,
b
?.
selectedIconTheme
,
t
),
groupAlignment:
lerpDouble
(
a
?.
groupAlignment
,
b
?.
groupAlignment
,
t
),
groupAlignment:
lerpDouble
(
a
?.
groupAlignment
,
b
?.
groupAlignment
,
t
),
labelType:
t
<
0.5
?
a
?.
labelType
:
b
?.
labelType
,
labelType:
t
<
0.5
?
a
?.
labelType
:
b
?.
labelType
,
useIndicator:
t
<
0.5
?
a
?.
useIndicator
:
b
?.
useIndicator
,
indicatorColor:
Color
.
lerp
(
a
?.
indicatorColor
,
b
?.
indicatorColor
,
t
),
);
);
}
}
...
@@ -132,6 +148,8 @@ class NavigationRailThemeData with Diagnosticable {
...
@@ -132,6 +148,8 @@ class NavigationRailThemeData with Diagnosticable {
selectedIconTheme
,
selectedIconTheme
,
groupAlignment
,
groupAlignment
,
labelType
,
labelType
,
useIndicator
,
indicatorColor
,
);
);
}
}
...
@@ -149,7 +167,9 @@ class NavigationRailThemeData with Diagnosticable {
...
@@ -149,7 +167,9 @@ class NavigationRailThemeData with Diagnosticable {
&&
other
.
unselectedIconTheme
==
unselectedIconTheme
&&
other
.
unselectedIconTheme
==
unselectedIconTheme
&&
other
.
selectedIconTheme
==
selectedIconTheme
&&
other
.
selectedIconTheme
==
selectedIconTheme
&&
other
.
groupAlignment
==
groupAlignment
&&
other
.
groupAlignment
==
groupAlignment
&&
other
.
labelType
==
labelType
;
&&
other
.
labelType
==
labelType
&&
other
.
useIndicator
==
useIndicator
&&
other
.
indicatorColor
==
indicatorColor
;
}
}
@override
@override
...
@@ -165,6 +185,8 @@ class NavigationRailThemeData with Diagnosticable {
...
@@ -165,6 +185,8 @@ class NavigationRailThemeData with Diagnosticable {
properties
.
add
(
DiagnosticsProperty
<
IconThemeData
>(
'selectedIconTheme'
,
selectedIconTheme
,
defaultValue:
defaultData
.
selectedIconTheme
));
properties
.
add
(
DiagnosticsProperty
<
IconThemeData
>(
'selectedIconTheme'
,
selectedIconTheme
,
defaultValue:
defaultData
.
selectedIconTheme
));
properties
.
add
(
DoubleProperty
(
'groupAlignment'
,
groupAlignment
,
defaultValue:
defaultData
.
groupAlignment
));
properties
.
add
(
DoubleProperty
(
'groupAlignment'
,
groupAlignment
,
defaultValue:
defaultData
.
groupAlignment
));
properties
.
add
(
DiagnosticsProperty
<
NavigationRailLabelType
>(
'labelType'
,
labelType
,
defaultValue:
defaultData
.
labelType
));
properties
.
add
(
DiagnosticsProperty
<
NavigationRailLabelType
>(
'labelType'
,
labelType
,
defaultValue:
defaultData
.
labelType
));
properties
.
add
(
DiagnosticsProperty
<
bool
>(
'useIndicator'
,
useIndicator
,
defaultValue:
defaultData
.
useIndicator
));
properties
.
add
(
ColorProperty
(
'indicatorColor'
,
indicatorColor
,
defaultValue:
defaultData
.
indicatorColor
));
}
}
}
}
...
...
packages/flutter/test/material/navigation_rail_test.dart
View file @
bd77118e
...
@@ -2160,6 +2160,195 @@ void main() {
...
@@ -2160,6 +2160,195 @@ void main() {
expect
(
secondItem
.
padding
,
secondItemPadding
);
expect
(
secondItem
.
padding
,
secondItemPadding
);
expect
(
thirdItem
.
padding
,
thirdItemPadding
);
expect
(
thirdItem
.
padding
,
thirdItemPadding
);
});
});
testWidgets
(
'NavigationRailDestination adds indicator by default when ThemeData.useMaterial3 is true'
,
(
WidgetTester
tester
)
async
{
await
_pumpNavigationRail
(
tester
,
theme:
ThemeData
(
useMaterial3:
true
),
navigationRail:
NavigationRail
(
labelType:
NavigationRailLabelType
.
selected
,
selectedIndex:
0
,
destinations:
const
<
NavigationRailDestination
>[
NavigationRailDestination
(
icon:
Icon
(
Icons
.
favorite_border
),
selectedIcon:
Icon
(
Icons
.
favorite
),
label:
Text
(
'Abc'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
bookmark_border
),
selectedIcon:
Icon
(
Icons
.
bookmark
),
label:
Text
(
'Def'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
star_border
),
selectedIcon:
Icon
(
Icons
.
star
),
label:
Text
(
'Ghi'
),
),
],
),
);
expect
(
find
.
byType
(
NavigationIndicator
),
findsWidgets
);
});
testWidgets
(
'NavigationRailDestination adds indicator when useIndicator is true'
,
(
WidgetTester
tester
)
async
{
await
_pumpNavigationRail
(
tester
,
navigationRail:
NavigationRail
(
useIndicator:
true
,
labelType:
NavigationRailLabelType
.
selected
,
selectedIndex:
0
,
destinations:
const
<
NavigationRailDestination
>[
NavigationRailDestination
(
icon:
Icon
(
Icons
.
favorite_border
),
selectedIcon:
Icon
(
Icons
.
favorite
),
label:
Text
(
'Abc'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
bookmark_border
),
selectedIcon:
Icon
(
Icons
.
bookmark
),
label:
Text
(
'Def'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
star_border
),
selectedIcon:
Icon
(
Icons
.
star
),
label:
Text
(
'Ghi'
),
),
],
),
);
expect
(
find
.
byType
(
NavigationIndicator
),
findsWidgets
);
});
testWidgets
(
'NavigationRailDestination does not add indicator when useIndicator is false'
,
(
WidgetTester
tester
)
async
{
await
_pumpNavigationRail
(
tester
,
navigationRail:
NavigationRail
(
useIndicator:
false
,
labelType:
NavigationRailLabelType
.
selected
,
selectedIndex:
0
,
destinations:
const
<
NavigationRailDestination
>[
NavigationRailDestination
(
icon:
Icon
(
Icons
.
favorite_border
),
selectedIcon:
Icon
(
Icons
.
favorite
),
label:
Text
(
'Abc'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
bookmark_border
),
selectedIcon:
Icon
(
Icons
.
bookmark
),
label:
Text
(
'Def'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
star_border
),
selectedIcon:
Icon
(
Icons
.
star
),
label:
Text
(
'Ghi'
),
),
],
),
);
expect
(
find
.
byType
(
NavigationIndicator
),
findsNothing
);
});
testWidgets
(
'NavigationRailDestination adds circular indicator when no labels are present'
,
(
WidgetTester
tester
)
async
{
await
_pumpNavigationRail
(
tester
,
navigationRail:
NavigationRail
(
useIndicator:
true
,
labelType:
NavigationRailLabelType
.
none
,
selectedIndex:
0
,
destinations:
const
<
NavigationRailDestination
>[
NavigationRailDestination
(
icon:
Icon
(
Icons
.
favorite_border
),
selectedIcon:
Icon
(
Icons
.
favorite
),
label:
Text
(
'Abc'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
bookmark_border
),
selectedIcon:
Icon
(
Icons
.
bookmark
),
label:
Text
(
'Def'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
star_border
),
selectedIcon:
Icon
(
Icons
.
star
),
label:
Text
(
'Ghi'
),
),
],
),
);
final
NavigationIndicator
indicator
=
tester
.
widget
<
NavigationIndicator
>(
find
.
byType
(
NavigationIndicator
).
first
);
expect
(
indicator
.
width
,
56
);
expect
(
indicator
.
height
,
56
);
});
testWidgets
(
'NavigationRailDestination adds circular indicator when selected labels are present'
,
(
WidgetTester
tester
)
async
{
await
_pumpNavigationRail
(
tester
,
navigationRail:
NavigationRail
(
useIndicator:
true
,
labelType:
NavigationRailLabelType
.
selected
,
selectedIndex:
0
,
destinations:
const
<
NavigationRailDestination
>[
NavigationRailDestination
(
icon:
Icon
(
Icons
.
favorite_border
),
selectedIcon:
Icon
(
Icons
.
favorite
),
label:
Text
(
'Abc'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
bookmark_border
),
selectedIcon:
Icon
(
Icons
.
bookmark
),
label:
Text
(
'Def'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
star_border
),
selectedIcon:
Icon
(
Icons
.
star
),
label:
Text
(
'Ghi'
),
),
],
),
);
final
NavigationIndicator
indicator
=
tester
.
widget
<
NavigationIndicator
>(
find
.
byType
(
NavigationIndicator
).
first
);
expect
(
indicator
.
width
,
56
);
expect
(
indicator
.
height
,
32
);
});
testWidgets
(
'NavigationRailDestination adds circular indicator when all labels are present'
,
(
WidgetTester
tester
)
async
{
await
_pumpNavigationRail
(
tester
,
navigationRail:
NavigationRail
(
useIndicator:
true
,
labelType:
NavigationRailLabelType
.
all
,
selectedIndex:
0
,
destinations:
const
<
NavigationRailDestination
>[
NavigationRailDestination
(
icon:
Icon
(
Icons
.
favorite_border
),
selectedIcon:
Icon
(
Icons
.
favorite
),
label:
Text
(
'Abc'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
bookmark_border
),
selectedIcon:
Icon
(
Icons
.
bookmark
),
label:
Text
(
'Def'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
star_border
),
selectedIcon:
Icon
(
Icons
.
star
),
label:
Text
(
'Ghi'
),
),
],
),
);
final
NavigationIndicator
indicator
=
tester
.
widget
<
NavigationIndicator
>(
find
.
byType
(
NavigationIndicator
).
first
);
expect
(
indicator
.
width
,
56
);
expect
(
indicator
.
height
,
32
);
});
}
}
TestSemantics
_expectedSemantics
(
)
{
TestSemantics
_expectedSemantics
(
)
{
...
@@ -2243,9 +2432,11 @@ Future<void> _pumpNavigationRail(
...
@@ -2243,9 +2432,11 @@ Future<void> _pumpNavigationRail(
WidgetTester
tester
,
{
WidgetTester
tester
,
{
double
textScaleFactor
=
1.0
,
double
textScaleFactor
=
1.0
,
required
NavigationRail
navigationRail
,
required
NavigationRail
navigationRail
,
ThemeData
?
theme
,
})
async
{
})
async
{
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
MaterialApp
(
MaterialApp
(
theme:
theme
,
home:
Builder
(
home:
Builder
(
builder:
(
BuildContext
context
)
{
builder:
(
BuildContext
context
)
{
return
MediaQuery
(
return
MediaQuery
(
...
...
packages/flutter/test/material/navigation_rail_theme_test.dart
View file @
bd77118e
...
@@ -36,6 +36,7 @@ void main() {
...
@@ -36,6 +36,7 @@ void main() {
expect
(
_unselectedLabelStyle
(
tester
).
fontSize
,
14.0
);
expect
(
_unselectedLabelStyle
(
tester
).
fontSize
,
14.0
);
expect
(
_destinationsAlign
(
tester
).
alignment
,
Alignment
.
topCenter
);
expect
(
_destinationsAlign
(
tester
).
alignment
,
Alignment
.
topCenter
);
expect
(
_labelType
(
tester
),
NavigationRailLabelType
.
none
);
expect
(
_labelType
(
tester
),
NavigationRailLabelType
.
none
);
expect
(
find
.
byType
(
NavigationIndicator
),
findsNothing
);
});
});
testWidgets
(
'NavigationRailThemeData values are used when no NavigationRail properties are specified'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'NavigationRailThemeData values are used when no NavigationRail properties are specified'
,
(
WidgetTester
tester
)
async
{
...
@@ -51,6 +52,8 @@ void main() {
...
@@ -51,6 +52,8 @@ void main() {
const
double
unselectedLabelFontSize
=
11.0
;
const
double
unselectedLabelFontSize
=
11.0
;
const
double
groupAlignment
=
0.0
;
const
double
groupAlignment
=
0.0
;
const
NavigationRailLabelType
labelType
=
NavigationRailLabelType
.
all
;
const
NavigationRailLabelType
labelType
=
NavigationRailLabelType
.
all
;
const
bool
useIndicator
=
true
;
const
Color
indicatorColor
=
Color
(
0x00000004
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
MaterialApp
(
MaterialApp
(
...
@@ -73,6 +76,8 @@ void main() {
...
@@ -73,6 +76,8 @@ void main() {
unselectedLabelTextStyle:
TextStyle
(
fontSize:
unselectedLabelFontSize
),
unselectedLabelTextStyle:
TextStyle
(
fontSize:
unselectedLabelFontSize
),
groupAlignment:
groupAlignment
,
groupAlignment:
groupAlignment
,
labelType:
labelType
,
labelType:
labelType
,
useIndicator:
useIndicator
,
indicatorColor:
indicatorColor
,
),
),
child:
NavigationRail
(
child:
NavigationRail
(
selectedIndex:
0
,
selectedIndex:
0
,
...
@@ -95,6 +100,8 @@ void main() {
...
@@ -95,6 +100,8 @@ void main() {
expect
(
_unselectedLabelStyle
(
tester
).
fontSize
,
unselectedLabelFontSize
);
expect
(
_unselectedLabelStyle
(
tester
).
fontSize
,
unselectedLabelFontSize
);
expect
(
_destinationsAlign
(
tester
).
alignment
,
Alignment
.
center
);
expect
(
_destinationsAlign
(
tester
).
alignment
,
Alignment
.
center
);
expect
(
_labelType
(
tester
),
labelType
);
expect
(
_labelType
(
tester
),
labelType
);
expect
(
find
.
byType
(
NavigationIndicator
),
findsWidgets
);
expect
(
_indicatorDecoration
(
tester
)?.
color
,
indicatorColor
);
});
});
testWidgets
(
'NavigationRail values take priority over NavigationRailThemeData values when both properties are specified'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'NavigationRail values take priority over NavigationRailThemeData values when both properties are specified'
,
(
WidgetTester
tester
)
async
{
...
@@ -110,6 +117,8 @@ void main() {
...
@@ -110,6 +117,8 @@ void main() {
const
double
unselectedLabelFontSize
=
11.0
;
const
double
unselectedLabelFontSize
=
11.0
;
const
double
groupAlignment
=
0.0
;
const
double
groupAlignment
=
0.0
;
const
NavigationRailLabelType
labelType
=
NavigationRailLabelType
.
all
;
const
NavigationRailLabelType
labelType
=
NavigationRailLabelType
.
all
;
const
bool
useIndicator
=
true
;
const
Color
indicatorColor
=
Color
(
0x00000004
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
MaterialApp
(
MaterialApp
(
...
@@ -132,6 +141,8 @@ void main() {
...
@@ -132,6 +141,8 @@ void main() {
unselectedLabelTextStyle:
TextStyle
(
fontSize:
7.0
),
unselectedLabelTextStyle:
TextStyle
(
fontSize:
7.0
),
groupAlignment:
1.0
,
groupAlignment:
1.0
,
labelType:
NavigationRailLabelType
.
selected
,
labelType:
NavigationRailLabelType
.
selected
,
useIndicator:
false
,
indicatorColor:
Color
(
0x00000096
),
),
),
child:
NavigationRail
(
child:
NavigationRail
(
selectedIndex:
0
,
selectedIndex:
0
,
...
@@ -152,6 +163,8 @@ void main() {
...
@@ -152,6 +163,8 @@ void main() {
unselectedLabelTextStyle:
const
TextStyle
(
fontSize:
unselectedLabelFontSize
),
unselectedLabelTextStyle:
const
TextStyle
(
fontSize:
unselectedLabelFontSize
),
groupAlignment:
groupAlignment
,
groupAlignment:
groupAlignment
,
labelType:
labelType
,
labelType:
labelType
,
useIndicator:
useIndicator
,
indicatorColor:
indicatorColor
,
),
),
),
),
),
),
...
@@ -170,6 +183,8 @@ void main() {
...
@@ -170,6 +183,8 @@ void main() {
expect
(
_unselectedLabelStyle
(
tester
).
fontSize
,
unselectedLabelFontSize
);
expect
(
_unselectedLabelStyle
(
tester
).
fontSize
,
unselectedLabelFontSize
);
expect
(
_destinationsAlign
(
tester
).
alignment
,
Alignment
.
center
);
expect
(
_destinationsAlign
(
tester
).
alignment
,
Alignment
.
center
);
expect
(
_labelType
(
tester
),
labelType
);
expect
(
_labelType
(
tester
),
labelType
);
expect
(
find
.
byType
(
NavigationIndicator
),
findsWidgets
);
expect
(
_indicatorDecoration
(
tester
)?.
color
,
indicatorColor
);
});
});
testWidgets
(
'Default debugFillProperties'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Default debugFillProperties'
,
(
WidgetTester
tester
)
async
{
...
@@ -195,6 +210,8 @@ void main() {
...
@@ -195,6 +210,8 @@ void main() {
unselectedLabelTextStyle:
TextStyle
(
fontSize:
7.0
),
unselectedLabelTextStyle:
TextStyle
(
fontSize:
7.0
),
groupAlignment:
1.0
,
groupAlignment:
1.0
,
labelType:
NavigationRailLabelType
.
selected
,
labelType:
NavigationRailLabelType
.
selected
,
useIndicator:
true
,
indicatorColor:
Color
(
0x00000096
),
).
debugFillProperties
(
builder
);
).
debugFillProperties
(
builder
);
final
List
<
String
>
description
=
builder
.
properties
final
List
<
String
>
description
=
builder
.
properties
...
@@ -215,7 +232,8 @@ void main() {
...
@@ -215,7 +232,8 @@ void main() {
expect
(
description
[
6
],
'groupAlignment: 1.0'
);
expect
(
description
[
6
],
'groupAlignment: 1.0'
);
expect
(
description
[
7
],
'labelType: NavigationRailLabelType.selected'
);
expect
(
description
[
7
],
'labelType: NavigationRailLabelType.selected'
);
expect
(
description
[
8
],
'useIndicator: true'
);
expect
(
description
[
9
],
'indicatorColor: Color(0x00000096)'
);
});
});
}
}
...
@@ -244,6 +262,16 @@ Material _railMaterial(WidgetTester tester) {
...
@@ -244,6 +262,16 @@ Material _railMaterial(WidgetTester tester) {
);
);
}
}
BoxDecoration
?
_indicatorDecoration
(
WidgetTester
tester
)
{
return
tester
.
firstWidget
<
Container
>(
find
.
descendant
(
of:
find
.
byType
(
NavigationIndicator
),
matching:
find
.
byType
(
Container
),
),
).
decoration
as
BoxDecoration
?;
}
IconThemeData
_selectedIconTheme
(
WidgetTester
tester
)
{
IconThemeData
_selectedIconTheme
(
WidgetTester
tester
)
{
return
_iconTheme
(
tester
,
Icons
.
favorite
);
return
_iconTheme
(
tester
,
Icons
.
favorite
);
}
}
...
...
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