Add indicatorColor
& indicatorShape
to NavigationRail
, NavigationDrawer
and move these properties from destination to NavigationBar
(#117049)
This commit is contained in:
parent
32da25053d
commit
cb988c7b6e
@ -93,6 +93,8 @@ class NavigationBar extends StatelessWidget {
|
||||
this.elevation,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.indicatorColor,
|
||||
this.indicatorShape,
|
||||
this.height,
|
||||
this.labelBehavior,
|
||||
}) : assert(destinations != null && destinations.length >= 2),
|
||||
@ -158,6 +160,20 @@ class NavigationBar extends StatelessWidget {
|
||||
/// overlay is applied.
|
||||
final Color? surfaceTintColor;
|
||||
|
||||
/// The color of the [indicatorShape] when this destination is selected.
|
||||
///
|
||||
/// If null, [NavigationBarThemeData.indicatorColor] is used. If that
|
||||
/// is also null and [ThemeData.useMaterial3] is true, [ColorScheme.secondaryContainer]
|
||||
/// is used. Otherwise, [ColorScheme.secondary] with an opacity of 0.24 is used.
|
||||
final Color? indicatorColor;
|
||||
|
||||
/// The shape of the selected inidicator.
|
||||
///
|
||||
/// If null, [NavigationBarThemeData.indicatorShape] is used. If that
|
||||
/// is also null and [ThemeData.useMaterial3] is true, [StadiumBorder] is used.
|
||||
/// Otherwise, [RoundedRectangleBorder] with a circular border radius of 16 is used.
|
||||
final ShapeBorder? indicatorShape;
|
||||
|
||||
/// The height of the [NavigationBar] itself.
|
||||
///
|
||||
/// If this is used in [Scaffold.bottomNavigationBar] and the scaffold is
|
||||
@ -224,6 +240,8 @@ class NavigationBar extends StatelessWidget {
|
||||
totalNumberOfDestinations: destinations.length,
|
||||
selectedAnimation: animation,
|
||||
labelBehavior: effectiveLabelBehavior,
|
||||
indicatorColor: indicatorColor,
|
||||
indicatorShape: indicatorShape,
|
||||
onTap: _handleTap(i),
|
||||
child: destinations[i],
|
||||
);
|
||||
@ -274,8 +292,6 @@ class NavigationDestination extends StatelessWidget {
|
||||
super.key,
|
||||
required this.icon,
|
||||
this.selectedIcon,
|
||||
this.indicatorColor,
|
||||
this.indicatorShape,
|
||||
required this.label,
|
||||
this.tooltip,
|
||||
});
|
||||
@ -300,12 +316,6 @@ class NavigationDestination extends StatelessWidget {
|
||||
/// would use a size of 24.0 and [ColorScheme.onSurface].
|
||||
final Widget? selectedIcon;
|
||||
|
||||
/// The color of the [indicatorShape] when this destination is selected.
|
||||
final Color? indicatorColor;
|
||||
|
||||
/// The shape of the selected inidicator.
|
||||
final ShapeBorder? indicatorShape;
|
||||
|
||||
/// The text label that appears below the icon of this
|
||||
/// [NavigationDestination].
|
||||
///
|
||||
@ -324,12 +334,13 @@ class NavigationDestination extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final _NavigationDestinationInfo info = _NavigationDestinationInfo.of(context);
|
||||
const Set<MaterialState> selectedState = <MaterialState>{MaterialState.selected};
|
||||
const Set<MaterialState> unselectedState = <MaterialState>{};
|
||||
|
||||
final NavigationBarThemeData navigationBarTheme = NavigationBarTheme.of(context);
|
||||
final NavigationBarThemeData defaults = _defaultsFor(context);
|
||||
final Animation<double> animation = _NavigationDestinationInfo.of(context).selectedAnimation;
|
||||
final Animation<double> animation = info.selectedAnimation;
|
||||
|
||||
return _NavigationDestinationBuilder(
|
||||
label: label,
|
||||
@ -351,8 +362,8 @@ class NavigationDestination extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
NavigationIndicator(
|
||||
animation: animation,
|
||||
color: indicatorColor ?? navigationBarTheme.indicatorColor ?? defaults.indicatorColor!,
|
||||
shape: indicatorShape ?? navigationBarTheme.indicatorShape ?? defaults.indicatorShape!
|
||||
color: info.indicatorColor ?? navigationBarTheme.indicatorColor ?? defaults.indicatorColor!,
|
||||
shape: info.indicatorShape ?? navigationBarTheme.indicatorShape ?? defaults.indicatorShape!
|
||||
),
|
||||
_StatusTransitionWidgetBuilder(
|
||||
animation: animation,
|
||||
@ -532,6 +543,8 @@ class _NavigationDestinationInfo extends InheritedWidget {
|
||||
required this.totalNumberOfDestinations,
|
||||
required this.selectedAnimation,
|
||||
required this.labelBehavior,
|
||||
required this.indicatorColor,
|
||||
required this.indicatorShape,
|
||||
required this.onTap,
|
||||
required super.child,
|
||||
});
|
||||
@ -588,6 +601,16 @@ class _NavigationDestinationInfo extends InheritedWidget {
|
||||
/// label, or hide all labels.
|
||||
final NavigationDestinationLabelBehavior labelBehavior;
|
||||
|
||||
/// The color of the selection indicator.
|
||||
///
|
||||
/// This is used by destinations to override the indicator color.
|
||||
final Color? indicatorColor;
|
||||
|
||||
/// The shape of the selection indicator.
|
||||
///
|
||||
/// This is used by destinations to override the indicator shape.
|
||||
final ShapeBorder? indicatorShape;
|
||||
|
||||
/// The callback that should be called when this destination is tapped.
|
||||
///
|
||||
/// This is computed by calling [NavigationBar.onDestinationSelected]
|
||||
|
@ -57,6 +57,8 @@ class NavigationDrawer extends StatelessWidget {
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.elevation,
|
||||
this.indicatorColor,
|
||||
this.indicatorShape,
|
||||
this.onDestinationSelected,
|
||||
this.selectedIndex = 0,
|
||||
});
|
||||
@ -90,6 +92,18 @@ class NavigationDrawer extends StatelessWidget {
|
||||
/// is also null, it will be 1.0.
|
||||
final double? elevation;
|
||||
|
||||
/// The color of the [indicatorShape] when this destination is selected.
|
||||
///
|
||||
/// If this is null, [NavigationDrawerThemeData.indicatorColor] is used.
|
||||
/// If that is also null, defaults to [ColorScheme.secondaryContainer].
|
||||
final Color? indicatorColor;
|
||||
|
||||
/// The shape of the selected inidicator.
|
||||
///
|
||||
/// If this is null, [NavigationDrawerThemeData.indicatorShape] is used.
|
||||
/// If that is also null, defaults to [StadiumBorder].
|
||||
final ShapeBorder? indicatorShape;
|
||||
|
||||
/// Defines the appearance of the items within the navigation drawer.
|
||||
///
|
||||
/// The list contains [NavigationDrawerDestination] widgets and/or customized
|
||||
@ -125,6 +139,8 @@ class NavigationDrawer extends StatelessWidget {
|
||||
index: index,
|
||||
totalNumberOfDestinations: totalNumberOfDestinations,
|
||||
selectedAnimation: animation,
|
||||
indicatorColor: indicatorColor,
|
||||
indicatorShape: indicatorShape,
|
||||
onTap: () {
|
||||
if (onDestinationSelected != null) {
|
||||
onDestinationSelected!(index);
|
||||
@ -315,9 +331,9 @@ class _NavigationDestinationBuilder extends StatelessWidget {
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
NavigationIndicator(
|
||||
animation: _NavigationDrawerDestinationInfo.of(context).selectedAnimation,
|
||||
color: navigationDrawerTheme.indicatorColor ?? defaults.indicatorColor!,
|
||||
shape: navigationDrawerTheme.indicatorShape ?? defaults.indicatorShape!,
|
||||
animation: info.selectedAnimation,
|
||||
color: info.indicatorColor ?? navigationDrawerTheme.indicatorColor ?? defaults.indicatorColor!,
|
||||
shape: info.indicatorShape ?? navigationDrawerTheme.indicatorShape ?? defaults.indicatorShape!,
|
||||
width: (navigationDrawerTheme.indicatorSize ?? defaults.indicatorSize!).width,
|
||||
height: (navigationDrawerTheme.indicatorSize ?? defaults.indicatorSize!).height,
|
||||
),
|
||||
@ -433,6 +449,8 @@ class _NavigationDrawerDestinationInfo extends InheritedWidget {
|
||||
required this.index,
|
||||
required this.totalNumberOfDestinations,
|
||||
required this.selectedAnimation,
|
||||
required this.indicatorColor,
|
||||
required this.indicatorShape,
|
||||
required this.onTap,
|
||||
required super.child,
|
||||
});
|
||||
@ -478,6 +496,16 @@ class _NavigationDrawerDestinationInfo extends InheritedWidget {
|
||||
/// to 1 (selected).
|
||||
final Animation<double> selectedAnimation;
|
||||
|
||||
/// The color of the indicator.
|
||||
///
|
||||
/// This is used by destinations to override the indicator color.
|
||||
final Color? indicatorColor;
|
||||
|
||||
/// The shape of the indicator.
|
||||
///
|
||||
/// This is used by destinations to override the indicator shape.
|
||||
final ShapeBorder? indicatorShape;
|
||||
|
||||
/// The callback that should be called when this destination is tapped.
|
||||
///
|
||||
/// This is computed by calling [NavigationDrawer.onDestinationSelected]
|
||||
|
@ -110,6 +110,7 @@ class NavigationRail extends StatefulWidget {
|
||||
this.minExtendedWidth,
|
||||
this.useIndicator,
|
||||
this.indicatorColor,
|
||||
this.indicatorShape,
|
||||
}) : assert(destinations != null && destinations.length >= 2),
|
||||
assert(selectedIndex == null || (0 <= selectedIndex && selectedIndex < destinations.length)),
|
||||
assert(elevation == null || elevation > 0),
|
||||
@ -306,8 +307,18 @@ class NavigationRail extends StatefulWidget {
|
||||
|
||||
/// Overrides the default value of [NavigationRail]'s selection indicator color,
|
||||
/// when [useIndicator] is true.
|
||||
///
|
||||
/// If this is null, [NavigationRailThemeData.indicatorColor] is used. If
|
||||
/// that is null, defaults to [ColorScheme.secondaryContainer].
|
||||
final Color? indicatorColor;
|
||||
|
||||
/// Overrides the default value of [NavigationRail]'s selection indicator shape,
|
||||
/// when [useIndicator] is true.
|
||||
///
|
||||
/// If this is null, [NavigationRailThemeData.indicatorShape] is used. If
|
||||
/// that is null, defaults to [StadiumBorder].
|
||||
final ShapeBorder? indicatorShape;
|
||||
|
||||
/// Returns the animation that controls the [NavigationRail.extended] state.
|
||||
///
|
||||
/// This can be used to synchronize animations in the [leading] or [trailing]
|
||||
@ -396,7 +407,7 @@ class _NavigationRailState extends State<NavigationRail> with TickerProviderStat
|
||||
final NavigationRailLabelType labelType = widget.labelType ?? navigationRailTheme.labelType ?? defaults.labelType!;
|
||||
final bool useIndicator = widget.useIndicator ?? navigationRailTheme.useIndicator ?? defaults.useIndicator!;
|
||||
final Color? indicatorColor = widget.indicatorColor ?? navigationRailTheme.indicatorColor ?? defaults.indicatorColor;
|
||||
final ShapeBorder? indicatorShape = navigationRailTheme.indicatorShape ?? defaults.indicatorShape;
|
||||
final ShapeBorder? indicatorShape = widget.indicatorShape ?? navigationRailTheme.indicatorShape ?? defaults.indicatorShape;
|
||||
|
||||
// For backwards compatibility, in M2 the opacity of the unselected icons needs
|
||||
// to be set to the default if it isn't in the given theme. This can be removed
|
||||
@ -900,6 +911,8 @@ class NavigationRailDestination {
|
||||
const NavigationRailDestination({
|
||||
required this.icon,
|
||||
Widget? selectedIcon,
|
||||
this.indicatorColor,
|
||||
this.indicatorShape,
|
||||
required this.label,
|
||||
this.padding,
|
||||
}) : selectedIcon = selectedIcon ?? icon,
|
||||
@ -933,6 +946,12 @@ class NavigationRailDestination {
|
||||
/// icons.
|
||||
final Widget selectedIcon;
|
||||
|
||||
/// The color of the [indicatorShape] when this destination is selected.
|
||||
final Color? indicatorColor;
|
||||
|
||||
/// The shape of the selection inidicator.
|
||||
final ShapeBorder? indicatorShape;
|
||||
|
||||
/// The label for the destination.
|
||||
///
|
||||
/// The label must be provided when used with the [NavigationRail]. When the
|
||||
|
@ -263,8 +263,8 @@ void main() {
|
||||
expect(_getMaterial(tester).surfaceTintColor, null);
|
||||
expect(_getMaterial(tester).elevation, 0);
|
||||
expect(tester.getSize(find.byType(NavigationBar)).height, 80);
|
||||
expect(_indicator(tester)?.color, const Color(0x3d2196f3));
|
||||
expect(_indicator(tester)?.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)));
|
||||
expect(_getIndicatorDecoration(tester)?.color, const Color(0x3d2196f3));
|
||||
expect(_getIndicatorDecoration(tester)?.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)));
|
||||
|
||||
// M3 settings from the token database.
|
||||
await tester.pumpWidget(
|
||||
@ -292,8 +292,8 @@ void main() {
|
||||
expect(_getMaterial(tester).surfaceTintColor, ThemeData().colorScheme.surfaceTint);
|
||||
expect(_getMaterial(tester).elevation, 3);
|
||||
expect(tester.getSize(find.byType(NavigationBar)).height, 80);
|
||||
expect(_indicator(tester)?.color, const Color(0xff2196f3));
|
||||
expect(_indicator(tester)?.shape, const StadiumBorder());
|
||||
expect(_getIndicatorDecoration(tester)?.color, const Color(0xff2196f3));
|
||||
expect(_getIndicatorDecoration(tester)?.shape, const StadiumBorder());
|
||||
});
|
||||
|
||||
testWidgets('NavigationBar shows tooltips with text scaling ', (WidgetTester tester) async {
|
||||
@ -807,21 +807,21 @@ void main() {
|
||||
testWidgets('Navigation destination updates indicator color and shape', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData(useMaterial3: true);
|
||||
const Color color = Color(0xff0000ff);
|
||||
const ShapeBorder shape = CircleBorder();
|
||||
const ShapeBorder shape = RoundedRectangleBorder();
|
||||
|
||||
Widget buildNaviagationBar({Color? indicatorColor, ShapeBorder? indicatorShape}) {
|
||||
Widget buildNavigationBar({Color? indicatorColor, ShapeBorder? indicatorShape}) {
|
||||
return MaterialApp(
|
||||
theme: theme,
|
||||
home: Scaffold(
|
||||
bottomNavigationBar: NavigationBar(
|
||||
destinations: <Widget>[
|
||||
indicatorColor: indicatorColor,
|
||||
indicatorShape: indicatorShape,
|
||||
destinations: const <Widget>[
|
||||
NavigationDestination(
|
||||
icon: const Icon(Icons.ac_unit),
|
||||
icon: Icon(Icons.ac_unit),
|
||||
label: 'AC',
|
||||
indicatorColor: indicatorColor,
|
||||
indicatorShape: indicatorShape,
|
||||
),
|
||||
const NavigationDestination(
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.access_alarm),
|
||||
label: 'Alarm',
|
||||
),
|
||||
@ -832,17 +832,17 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildNaviagationBar());
|
||||
await tester.pumpWidget(buildNavigationBar());
|
||||
|
||||
// Test default indicator color and shape.
|
||||
expect(_indicator(tester)?.color, theme.colorScheme.secondaryContainer);
|
||||
expect(_indicator(tester)?.shape, const StadiumBorder());
|
||||
expect(_getIndicatorDecoration(tester)?.color, theme.colorScheme.secondaryContainer);
|
||||
expect(_getIndicatorDecoration(tester)?.shape, const StadiumBorder());
|
||||
|
||||
await tester.pumpWidget(buildNaviagationBar(indicatorColor: color, indicatorShape: shape));
|
||||
await tester.pumpWidget(buildNavigationBar(indicatorColor: color, indicatorShape: shape));
|
||||
|
||||
// Test custom indicator color and shape.
|
||||
expect(_indicator(tester)?.color, color);
|
||||
expect(_indicator(tester)?.shape, shape);
|
||||
expect(_getIndicatorDecoration(tester)?.color, color);
|
||||
expect(_getIndicatorDecoration(tester)?.shape, shape);
|
||||
});
|
||||
|
||||
group('Material 2', () {
|
||||
@ -852,21 +852,21 @@ void main() {
|
||||
testWidgets('Navigation destination updates indicator color and shape', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData(useMaterial3: false);
|
||||
const Color color = Color(0xff0000ff);
|
||||
const ShapeBorder shape = CircleBorder();
|
||||
const ShapeBorder shape = RoundedRectangleBorder();
|
||||
|
||||
Widget buildNaviagationBar({Color? indicatorColor, ShapeBorder? indicatorShape}) {
|
||||
Widget buildNavigationBar({Color? indicatorColor, ShapeBorder? indicatorShape}) {
|
||||
return MaterialApp(
|
||||
theme: theme,
|
||||
home: Scaffold(
|
||||
bottomNavigationBar: NavigationBar(
|
||||
destinations: <Widget>[
|
||||
indicatorColor: indicatorColor,
|
||||
indicatorShape: indicatorShape,
|
||||
destinations: const <Widget>[
|
||||
NavigationDestination(
|
||||
icon: const Icon(Icons.ac_unit),
|
||||
icon: Icon(Icons.ac_unit),
|
||||
label: 'AC',
|
||||
indicatorColor: indicatorColor,
|
||||
indicatorShape: indicatorShape,
|
||||
),
|
||||
const NavigationDestination(
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.access_alarm),
|
||||
label: 'Alarm',
|
||||
),
|
||||
@ -877,20 +877,20 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildNaviagationBar());
|
||||
await tester.pumpWidget(buildNavigationBar());
|
||||
|
||||
// Test default indicator color and shape.
|
||||
expect(_indicator(tester)?.color, theme.colorScheme.secondary.withOpacity(0.24));
|
||||
expect(_getIndicatorDecoration(tester)?.color, theme.colorScheme.secondary.withOpacity(0.24));
|
||||
expect(
|
||||
_indicator(tester)?.shape,
|
||||
_getIndicatorDecoration(tester)?.shape,
|
||||
const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildNaviagationBar(indicatorColor: color, indicatorShape: shape));
|
||||
await tester.pumpWidget(buildNavigationBar(indicatorColor: color, indicatorShape: shape));
|
||||
|
||||
// Test custom indicator color and shape.
|
||||
expect(_indicator(tester)?.color, color);
|
||||
expect(_indicator(tester)?.shape, shape);
|
||||
expect(_getIndicatorDecoration(tester)?.color, color);
|
||||
expect(_getIndicatorDecoration(tester)?.shape, shape);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -912,7 +912,7 @@ Material _getMaterial(WidgetTester tester) {
|
||||
);
|
||||
}
|
||||
|
||||
ShapeDecoration? _indicator(WidgetTester tester) {
|
||||
ShapeDecoration? _getIndicatorDecoration(WidgetTester tester) {
|
||||
return tester.firstWidget<Container>(
|
||||
find.descendant(
|
||||
of: find.byType(FadeTransition),
|
||||
|
@ -23,7 +23,7 @@ void main() {
|
||||
),
|
||||
NavigationDrawerDestination(
|
||||
icon: Icon(Icons.access_alarm, color: theme.iconTheme.color),
|
||||
label: Text('Alarm',style: theme.textTheme.bodySmall),
|
||||
label: Text('Alarm', style: theme.textTheme.bodySmall),
|
||||
),
|
||||
],
|
||||
onDestinationSelected: (int i) {
|
||||
@ -68,7 +68,7 @@ void main() {
|
||||
),
|
||||
NavigationDrawerDestination(
|
||||
icon: Icon(Icons.access_alarm, color: theme.iconTheme.color),
|
||||
label: Text('Alarm',style: theme.textTheme.bodySmall),
|
||||
label: Text('Alarm', style: theme.textTheme.bodySmall),
|
||||
),
|
||||
],
|
||||
onDestinationSelected: (int i) {},
|
||||
@ -97,7 +97,7 @@ void main() {
|
||||
),
|
||||
NavigationDrawerDestination(
|
||||
icon: Icon(Icons.access_alarm, color: theme.iconTheme.color),
|
||||
label: Text('Alarm',style: theme.textTheme.bodySmall),
|
||||
label: Text('Alarm', style: theme.textTheme.bodySmall),
|
||||
),
|
||||
],
|
||||
);
|
||||
@ -134,7 +134,7 @@ void main() {
|
||||
),
|
||||
NavigationDrawerDestination(
|
||||
icon: Icon(Icons.access_alarm, color: theme.iconTheme.color),
|
||||
label: Text('Alarm',style: theme.textTheme.bodySmall),
|
||||
label: Text('Alarm', style: theme.textTheme.bodySmall),
|
||||
),
|
||||
],
|
||||
onDestinationSelected: (int i) {},
|
||||
@ -149,8 +149,8 @@ void main() {
|
||||
expect(_getMaterial(tester).surfaceTintColor,
|
||||
ThemeData().colorScheme.surfaceTint);
|
||||
expect(_getMaterial(tester).elevation, 1);
|
||||
expect(_indicator(tester)?.color, const Color(0xff2196f3));
|
||||
expect(_indicator(tester)?.shape, const StadiumBorder());
|
||||
expect(_getIndicatorDecoration(tester)?.color, const Color(0xff2196f3));
|
||||
expect(_getIndicatorDecoration(tester)?.shape, const StadiumBorder());
|
||||
});
|
||||
|
||||
testWidgets('Navigation drawer semantics', (WidgetTester tester) async {
|
||||
@ -169,7 +169,7 @@ void main() {
|
||||
),
|
||||
NavigationDrawerDestination(
|
||||
icon: Icon(Icons.access_alarm, color: theme.iconTheme.color),
|
||||
label: Text('Alarm',style: theme.textTheme.bodySmall),
|
||||
label: Text('Alarm', style: theme.textTheme.bodySmall),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -222,6 +222,53 @@ void main() {
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Navigation destination updates indicator color and shape', (WidgetTester tester) async {
|
||||
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
final ThemeData theme = ThemeData(useMaterial3: true);
|
||||
const Color color = Color(0xff0000ff);
|
||||
const ShapeBorder shape = RoundedRectangleBorder();
|
||||
|
||||
Widget buildNavigationDrawer({Color? indicatorColor, ShapeBorder? indicatorShape}) {
|
||||
return MaterialApp(
|
||||
theme: theme,
|
||||
home: Scaffold(
|
||||
key: scaffoldKey,
|
||||
drawer: NavigationDrawer(
|
||||
indicatorColor: indicatorColor,
|
||||
indicatorShape: indicatorShape,
|
||||
children: <Widget>[
|
||||
Text('Headline', style: theme.textTheme.bodyLarge),
|
||||
const NavigationDrawerDestination(
|
||||
icon: Icon(Icons.ac_unit),
|
||||
label: Text('AC'),
|
||||
),
|
||||
const NavigationDrawerDestination(
|
||||
icon: Icon(Icons.access_alarm),
|
||||
label: Text('Alarm'),
|
||||
),
|
||||
],
|
||||
onDestinationSelected: (int i) { },
|
||||
),
|
||||
body: Container(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildNavigationDrawer());
|
||||
scaffoldKey.currentState!.openDrawer();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Test default indicator color and shape.
|
||||
expect(_getIndicatorDecoration(tester)?.color, theme.colorScheme.secondaryContainer);
|
||||
expect(_getIndicatorDecoration(tester)?.shape, const StadiumBorder());
|
||||
|
||||
await tester.pumpWidget(buildNavigationDrawer(indicatorColor: color, indicatorShape: shape));
|
||||
|
||||
// Test custom indicator color and shape.
|
||||
expect(_getIndicatorDecoration(tester)?.color, color);
|
||||
expect(_getIndicatorDecoration(tester)?.shape, shape);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildWidget(GlobalKey<ScaffoldState> scaffoldKey, Widget child) {
|
||||
@ -242,7 +289,7 @@ Material _getMaterial(WidgetTester tester) {
|
||||
);
|
||||
}
|
||||
|
||||
ShapeDecoration? _indicator(WidgetTester tester) {
|
||||
ShapeDecoration? _getIndicatorDecoration(WidgetTester tester) {
|
||||
return tester
|
||||
.firstWidget<Container>(
|
||||
find.descendant(
|
||||
|
@ -2846,6 +2846,50 @@ void main() {
|
||||
expect(transform.getColumn(0)[0], 1.0);
|
||||
});
|
||||
|
||||
testWidgets('Navigation destination updates indicator color and shape', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData(useMaterial3: true);
|
||||
const Color color = Color(0xff0000ff);
|
||||
const ShapeBorder shape = RoundedRectangleBorder();
|
||||
|
||||
Widget buildNavigationRail({Color? indicatorColor, ShapeBorder? indicatorShape}) {
|
||||
return MaterialApp(
|
||||
theme: theme,
|
||||
home: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Row(
|
||||
children: <Widget>[
|
||||
NavigationRail(
|
||||
useIndicator: true,
|
||||
indicatorColor: indicatorColor,
|
||||
indicatorShape: indicatorShape,
|
||||
selectedIndex: 0,
|
||||
destinations: _destinations(),
|
||||
),
|
||||
const Expanded(
|
||||
child: Text('body'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildNavigationRail());
|
||||
|
||||
// Test default indicator color and shape.
|
||||
expect(_getIndicatorDecoration(tester)?.color, theme.colorScheme.secondaryContainer);
|
||||
expect(_getIndicatorDecoration(tester)?.shape, const StadiumBorder());
|
||||
|
||||
await tester.pumpWidget(buildNavigationRail(indicatorColor: color, indicatorShape: shape));
|
||||
|
||||
// Test custom indicator color and shape.
|
||||
expect(_getIndicatorDecoration(tester)?.color, color);
|
||||
expect(_getIndicatorDecoration(tester)?.shape, shape);
|
||||
});
|
||||
|
||||
group('Material 2', () {
|
||||
// Original Material 2 tests. Remove this group after `useMaterial3` has been deprecated.
|
||||
testWidgets('Renders at the correct default width - [labelType]=none (default)', (WidgetTester tester) async {
|
||||
@ -4655,7 +4699,6 @@ void main() {
|
||||
final double updatedWidthRTL = tester.getSize(find.byType(NavigationRail)).width;
|
||||
expect(updatedWidthRTL, defaultWidth + safeAreaPadding);
|
||||
});
|
||||
|
||||
}); // End Material 2 group
|
||||
}
|
||||
|
||||
@ -4878,3 +4921,12 @@ Widget _buildWidget(Widget child, {bool useMaterial3 = true, bool isRTL = false}
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
ShapeDecoration? _getIndicatorDecoration(WidgetTester tester) {
|
||||
return tester.firstWidget<Container>(
|
||||
find.descendant(
|
||||
of: find.byType(FadeTransition),
|
||||
matching: find.byType(Container),
|
||||
),
|
||||
).decoration as ShapeDecoration?;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user