extendedAnimation static method
Returns the animation that controls the NavigationRail.extended state.
This can be used to synchronize animations in the leading or trailing widget, such as an animated menu or a FloatingActionButton animation.
This example shows how to use this animation to create a FloatingActionButton that animates itself between the normal and extended states of the NavigationRail.
An instance of MyNavigationRailFab is created for NavigationRail.leading.
Pressing the FAB button toggles the "extended" state of the NavigationRail.
To see it in action, copy and run this code snippet on DartPad.
import 'dart:ui';
import 'package:material_ui/material_ui.dart';
/// Flutter code sample for [NavigationRail.extendedAnimation].
void main() => runApp(const ExtendedAnimationExampleApp());
class ExtendedAnimationExampleApp extends StatelessWidget {
const ExtendedAnimationExampleApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: Scaffold(body: MyNavigationRail()));
}
}
class MyNavigationRail extends StatefulWidget {
const MyNavigationRail({super.key});
@override
State<MyNavigationRail> createState() => _MyNavigationRailState();
}
class _MyNavigationRailState extends State<MyNavigationRail> {
int _selectedIndex = 0;
bool _extended = false;
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
NavigationRail(
selectedIndex: _selectedIndex,
extended: _extended,
leading: MyNavigationRailFab(
onPressed: () {
setState(() {
_extended = !_extended;
});
},
),
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
labelType: .none,
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('First'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.book),
label: Text('Second'),
),
NavigationRailDestination(
icon: Icon(Icons.star_border),
selectedIcon: Icon(Icons.star),
label: Text('Third'),
),
],
),
const VerticalDivider(thickness: 1, width: 1),
// This is the main content.
Expanded(
child: Center(
child: Column(
mainAxisAlignment: .center,
children: <Widget>[
const Text('Tap on FloatingActionButton to expand'),
const SizedBox(height: 20),
Text('selectedIndex: $_selectedIndex'),
],
),
),
),
],
);
}
}
class MyNavigationRailFab extends StatelessWidget {
const MyNavigationRailFab({super.key, this.onPressed});
final VoidCallback? onPressed;
@override
Widget build(BuildContext context) {
final Animation<double> animation = NavigationRail.extendedAnimation(
context,
);
return AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget? child) {
// The extended fab has a shorter height than the regular fab.
return Container(
height: 56,
padding: .symmetric(vertical: lerpDouble(0, 6, animation.value)!),
child: animation.value == 0
? FloatingActionButton(
onPressed: onPressed,
child: const Icon(Icons.add),
)
: Align(
alignment: .centerStart,
widthFactor: animation.value,
child: Padding(
padding: const .directional(start: 8),
child: FloatingActionButton.extended(
icon: const Icon(Icons.add),
label: const Text('CREATE'),
onPressed: onPressed,
),
),
),
);
},
);
}
}
Implementation
// TODO(framework): Replace the following block with a @dartpad directive
// when it's supported. https://github.com/dart-lang/dartdoc/issues/4123
/// {@macro material_ui.dartpad_guide}
///
/// {@example /example/lib/navigation_rail/navigation_rail.extended_animation.0.dart#body}
///
/// </callout-box>
static Animation<double> extendedAnimation(BuildContext context) {
return context
.dependOnInheritedWidgetOfExactType<_ExtendedNavigationRailAnimation>()!
.animation;
}