Unverified Commit 3479aaba authored by Hans Muller's avatar Hans Muller Committed by GitHub

Updated the nested navigation NavigationBar example (#137788)

Updated the NavigationBar API doc that describes
examples/api/lib/material/navigation_bar/navigation_bar.2.dart and made
some cosmetic changes to the example to improve its appearance in
Material 3. Also did a little gratuitous reformatting.

Fixes #136125
parent dca1f9e5
...@@ -32,33 +32,47 @@ class _HomeState extends State<Home> with TickerProviderStateMixin<Home> { ...@@ -32,33 +32,47 @@ class _HomeState extends State<Home> with TickerProviderStateMixin<Home> {
int selectedIndex = 0; int selectedIndex = 0;
AnimationController buildFaderController() { AnimationController buildFaderController() {
final AnimationController controller = final AnimationController controller = AnimationController(
AnimationController(vsync: this, duration: const Duration(milliseconds: 200)); vsync: this,
controller.addStatusListener((AnimationStatus status) { duration: const Duration(milliseconds: 300),
if (status == AnimationStatus.dismissed) { );
setState(() {}); // Rebuild unselected destinations offstage. controller.addStatusListener(
} (AnimationStatus status) {
}); if (status == AnimationStatus.dismissed) {
setState(() {}); // Rebuild unselected destinations offstage.
}
},
);
return controller; return controller;
} }
@override @override
void initState() { void initState() {
super.initState(); super.initState();
navigatorKeys =
List<GlobalKey<NavigatorState>>.generate(allDestinations.length, (int index) => GlobalKey()).toList(); navigatorKeys = List<GlobalKey<NavigatorState>>.generate(
destinationFaders = allDestinations.length,
List<AnimationController>.generate(allDestinations.length, (int index) => buildFaderController()).toList(); (int index) => GlobalKey(),
).toList();
destinationFaders = List<AnimationController>.generate(
allDestinations.length,
(int index) => buildFaderController(),
).toList();
destinationFaders[selectedIndex].value = 1.0; destinationFaders[selectedIndex].value = 1.0;
destinationViews = allDestinations.map((Destination destination) {
return FadeTransition( final CurveTween tween = CurveTween(curve: Curves.fastOutSlowIn);
opacity: destinationFaders[destination.index].drive(CurveTween(curve: Curves.fastOutSlowIn)), destinationViews = allDestinations.map<Widget>(
child: DestinationView( (Destination destination) {
destination: destination, return FadeTransition(
navigatorKey: navigatorKeys[destination.index], opacity: destinationFaders[destination.index].drive(tween),
), child: DestinationView(
); destination: destination,
}).toList(); navigatorKey: navigatorKeys[destination.index],
),
);
},
).toList();
} }
@override @override
...@@ -81,20 +95,22 @@ class _HomeState extends State<Home> with TickerProviderStateMixin<Home> { ...@@ -81,20 +95,22 @@ class _HomeState extends State<Home> with TickerProviderStateMixin<Home> {
top: false, top: false,
child: Stack( child: Stack(
fit: StackFit.expand, fit: StackFit.expand,
children: allDestinations.map((Destination destination) { children: allDestinations.map(
final int index = destination.index; (Destination destination) {
final Widget view = destinationViews[index]; final int index = destination.index;
if (index == selectedIndex) { final Widget view = destinationViews[index];
destinationFaders[index].forward(); if (index == selectedIndex) {
return Offstage(offstage: false, child: view); destinationFaders[index].forward();
} else { return Offstage(offstage: false, child: view);
destinationFaders[index].reverse(); } else {
if (destinationFaders[index].isAnimating) { destinationFaders[index].reverse();
return IgnorePointer(child: view); if (destinationFaders[index].isAnimating) {
return IgnorePointer(child: view);
}
return Offstage(child: view);
} }
return Offstage(child: view); },
} ).toList(),
}).toList(),
), ),
), ),
bottomNavigationBar: NavigationBar( bottomNavigationBar: NavigationBar(
...@@ -104,12 +120,14 @@ class _HomeState extends State<Home> with TickerProviderStateMixin<Home> { ...@@ -104,12 +120,14 @@ class _HomeState extends State<Home> with TickerProviderStateMixin<Home> {
selectedIndex = index; selectedIndex = index;
}); });
}, },
destinations: allDestinations.map((Destination destination) { destinations: allDestinations.map<NavigationDestination>(
return NavigationDestination( (Destination destination) {
icon: Icon(destination.icon, color: destination.color), return NavigationDestination(
label: destination.title, icon: Icon(destination.icon, color: destination.color),
); label: destination.title,
}).toList(), );
},
).toList(),
), ),
), ),
); );
...@@ -148,6 +166,7 @@ class RootPage extends StatelessWidget { ...@@ -148,6 +166,7 @@ class RootPage extends StatelessWidget {
final TextStyle headlineSmall = Theme.of(context).textTheme.headlineSmall!; final TextStyle headlineSmall = Theme.of(context).textTheme.headlineSmall!;
final ButtonStyle buttonStyle = ElevatedButton.styleFrom( final ButtonStyle buttonStyle = ElevatedButton.styleFrom(
backgroundColor: destination.color, backgroundColor: destination.color,
foregroundColor: Colors.white,
visualDensity: VisualDensity.comfortable, visualDensity: VisualDensity.comfortable,
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
textStyle: headlineSmall, textStyle: headlineSmall,
...@@ -157,6 +176,7 @@ class RootPage extends StatelessWidget { ...@@ -157,6 +176,7 @@ class RootPage extends StatelessWidget {
appBar: AppBar( appBar: AppBar(
title: Text('${destination.title} RootPage - /'), title: Text('${destination.title} RootPage - /'),
backgroundColor: destination.color, backgroundColor: destination.color,
foregroundColor: Colors.white,
), ),
backgroundColor: destination.color[50], backgroundColor: destination.color[50],
body: Center( body: Center(
...@@ -236,15 +256,23 @@ class ListPage extends StatelessWidget { ...@@ -236,15 +256,23 @@ class ListPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
const int itemCount = 50; const int itemCount = 50;
final ColorScheme colorScheme = Theme.of(context).colorScheme;
final ButtonStyle buttonStyle = OutlinedButton.styleFrom( final ButtonStyle buttonStyle = OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: BorderSide(
color: colorScheme.onSurface.withOpacity(0.12),
),
),
foregroundColor: destination.color, foregroundColor: destination.color,
fixedSize: const Size.fromHeight(128), fixedSize: const Size.fromHeight(64),
textStyle: Theme.of(context).textTheme.headlineSmall, textStyle: Theme.of(context).textTheme.headlineSmall,
); );
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('${destination.title} ListPage - /list'), title: Text('${destination.title} ListPage - /list'),
backgroundColor: destination.color, backgroundColor: destination.color,
foregroundColor: Colors.white,
), ),
backgroundColor: destination.color[50], backgroundColor: destination.color[50],
body: SizedBox.expand( body: SizedBox.expand(
...@@ -256,7 +284,11 @@ class ListPage extends StatelessWidget { ...@@ -256,7 +284,11 @@ class ListPage extends StatelessWidget {
child: OutlinedButton( child: OutlinedButton(
style: buttonStyle.copyWith( style: buttonStyle.copyWith(
backgroundColor: MaterialStatePropertyAll<Color>( backgroundColor: MaterialStatePropertyAll<Color>(
Color.lerp(destination.color[100], Colors.white, index / itemCount)!, Color.lerp(
destination.color[100],
Colors.white,
index / itemCount
)!,
), ),
), ),
onPressed: () { onPressed: () {
...@@ -303,6 +335,7 @@ class _TextPageState extends State<TextPage> { ...@@ -303,6 +335,7 @@ class _TextPageState extends State<TextPage> {
appBar: AppBar( appBar: AppBar(
title: Text('${widget.destination.title} TextPage - /list/text'), title: Text('${widget.destination.title} TextPage - /list/text'),
backgroundColor: widget.destination.color, backgroundColor: widget.destination.color,
foregroundColor: Colors.white,
), ),
backgroundColor: widget.destination.color[50], backgroundColor: widget.destination.color[50],
body: Container( body: Container(
......
...@@ -62,12 +62,18 @@ const double _kIndicatorWidth = 64; ...@@ -62,12 +62,18 @@ const double _kIndicatorWidth = 64;
/// {@end-tool} /// {@end-tool}
/// ///
/// {@tool dartpad} /// {@tool dartpad}
/// This example shows a [NavigationBar] as it is used within a [Scaffold] /// This example shows a [NavigationBar] within a main [Scaffold]
/// widget when there are nested navigators that provide local navigation. The /// widget that's used to control the visibility of destination pages.
/// [NavigationBar] has four [NavigationDestination] widgets with different /// Each destination has its own scaffold and a nested navigator that
/// color schemes. The [onDestinationSelected] callback changes the selected /// provides local navigation. The example's [NavigationBar] has four
/// item's index and displays a corresponding page with its own local navigator /// [NavigationDestination] widgets with different color schemes. Its
/// in the body of a [Scaffold]. /// [onDestinationSelected] callback changes the selected
/// destination's index and displays a corresponding page with its own
/// local navigator and scaffold - all within the body of the main
/// scaffold. The destination pages are organized in a [Stack] and
/// switching destinations fades out the current page and
/// fades in the new one. Destinations that aren't visible or animating
/// are kept [Offstage].
/// ///
/// ** See code in examples/api/lib/material/navigation_bar/navigation_bar.2.dart ** /// ** See code in examples/api/lib/material/navigation_bar/navigation_bar.2.dart **
/// {@end-tool} /// {@end-tool}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment