@@ -295,6 +295,7 @@ class NavigationDestination extends StatelessWidget {
295295 this .selectedIcon,
296296 required this .label,
297297 this .tooltip,
298+ this .enabled = true ,
298299 });
299300
300301 /// The [Widget] (usually an [Icon] ) that's displayed for this
@@ -333,11 +334,17 @@ class NavigationDestination extends StatelessWidget {
333334 /// Defaults to null, in which case the [label] text will be used.
334335 final String ? tooltip;
335336
337+ /// Indicates that this destination is selectable.
338+ ///
339+ /// Defaults to true.
340+ final bool enabled;
341+
336342 @override
337343 Widget build (BuildContext context) {
338344 final _NavigationDestinationInfo info = _NavigationDestinationInfo .of (context);
339345 const Set <MaterialState > selectedState = < MaterialState > {MaterialState .selected};
340346 const Set <MaterialState > unselectedState = < MaterialState > {};
347+ const Set <MaterialState > disabledState = < MaterialState > {MaterialState .disabled};
341348
342349 final NavigationBarThemeData navigationBarTheme = NavigationBarTheme .of (context);
343350 final NavigationBarThemeData defaults = _defaultsFor (context);
@@ -346,15 +353,24 @@ class NavigationDestination extends StatelessWidget {
346353 return _NavigationDestinationBuilder (
347354 label: label,
348355 tooltip: tooltip,
356+ enabled: enabled,
349357 buildIcon: (BuildContext context) {
358+ final IconThemeData selectedIconTheme =
359+ navigationBarTheme.iconTheme? .resolve (selectedState)
360+ ?? defaults.iconTheme! .resolve (selectedState)! ;
361+ final IconThemeData unselectedIconTheme =
362+ navigationBarTheme.iconTheme? .resolve (unselectedState)
363+ ?? defaults.iconTheme! .resolve (unselectedState)! ;
364+ final IconThemeData disabledIconTheme =
365+ navigationBarTheme.iconTheme? .resolve (disabledState)
366+ ?? defaults.iconTheme! .resolve (disabledState)! ;
367+
350368 final Widget selectedIconWidget = IconTheme .merge (
351- data: navigationBarTheme.iconTheme? .resolve (selectedState)
352- ?? defaults.iconTheme! .resolve (selectedState)! ,
369+ data: enabled ? selectedIconTheme : disabledIconTheme,
353370 child: selectedIcon ?? icon,
354371 );
355372 final Widget unselectedIconWidget = IconTheme .merge (
356- data: navigationBarTheme.iconTheme? .resolve (unselectedState)
357- ?? defaults.iconTheme! .resolve (unselectedState)! ,
373+ data: enabled ? unselectedIconTheme : disabledIconTheme,
358374 child: icon,
359375 );
360376
@@ -382,7 +398,15 @@ class NavigationDestination extends StatelessWidget {
382398 ?? defaults.labelTextStyle! .resolve (selectedState);
383399 final TextStyle ? effectiveUnselectedLabelTextStyle = navigationBarTheme.labelTextStyle? .resolve (unselectedState)
384400 ?? defaults.labelTextStyle! .resolve (unselectedState);
385- final TextStyle ? textStyle = _isForwardOrCompleted (animation) ? effectiveSelectedLabelTextStyle : effectiveUnselectedLabelTextStyle;
401+ final TextStyle ? effectiveDisabledLabelTextStyle = navigationBarTheme.labelTextStyle? .resolve (disabledState)
402+ ?? defaults.labelTextStyle! .resolve (disabledState);
403+
404+ final TextStyle ? textStyle = enabled
405+ ? _isForwardOrCompleted (animation)
406+ ? effectiveSelectedLabelTextStyle
407+ : effectiveUnselectedLabelTextStyle
408+ : effectiveDisabledLabelTextStyle;
409+
386410 return Padding (
387411 padding: const EdgeInsets .only (top: 4 ),
388412 child: MediaQuery .withClampedTextScaling (
@@ -416,6 +440,7 @@ class _NavigationDestinationBuilder extends StatefulWidget {
416440 required this .buildLabel,
417441 required this .label,
418442 this .tooltip,
443+ this .enabled = true ,
419444 });
420445
421446 /// Builds the icon for a destination in a [NavigationBar] .
@@ -454,6 +479,11 @@ class _NavigationDestinationBuilder extends StatefulWidget {
454479 /// Defaults to null, in which case the [label] text will be used.
455480 final String ? tooltip;
456481
482+ /// Indicates that this destination is selectable.
483+ ///
484+ /// Defaults to true.
485+ final bool enabled;
486+
457487 @override
458488 State <_NavigationDestinationBuilder > createState () => _NavigationDestinationBuilderState ();
459489}
@@ -474,7 +504,7 @@ class _NavigationDestinationBuilderState extends State<_NavigationDestinationBui
474504 iconKey: iconKey,
475505 labelBehavior: info.labelBehavior,
476506 customBorder: navigationBarTheme.indicatorShape ?? defaults.indicatorShape,
477- onTap: info.onTap,
507+ onTap: widget.enabled ? info.onTap : null ,
478508 child: Row (
479509 children: < Widget > [
480510 Expanded (
@@ -1319,9 +1349,11 @@ class _NavigationBarDefaultsM3 extends NavigationBarThemeData {
13191349 return MaterialStateProperty .resolveWith ((Set <MaterialState > states) {
13201350 return IconThemeData (
13211351 size: 24.0 ,
1322- color: states.contains (MaterialState .selected)
1323- ? _colors.onSecondaryContainer
1324- : _colors.onSurfaceVariant,
1352+ color: states.contains (MaterialState .disabled)
1353+ ? _colors.onSurfaceVariant.withOpacity (0.38 )
1354+ : states.contains (MaterialState .selected)
1355+ ? _colors.onSecondaryContainer
1356+ : _colors.onSurfaceVariant,
13251357 );
13261358 });
13271359 }
@@ -1332,9 +1364,11 @@ class _NavigationBarDefaultsM3 extends NavigationBarThemeData {
13321364 @override MaterialStateProperty <TextStyle ?>? get labelTextStyle {
13331365 return MaterialStateProperty .resolveWith ((Set <MaterialState > states) {
13341366 final TextStyle style = _textTheme.labelMedium! ;
1335- return style.apply (color: states.contains (MaterialState .selected)
1336- ? _colors.onSurface
1337- : _colors.onSurfaceVariant
1367+ return style.apply (color: states.contains (MaterialState .disabled)
1368+ ? _colors.onSurfaceVariant.withOpacity (0.38 )
1369+ : states.contains (MaterialState .selected)
1370+ ? _colors.onSurface
1371+ : _colors.onSurfaceVariant
13381372 );
13391373 });
13401374 }
0 commit comments