BottomAppBar class
A container that is typically used with Scaffold.bottomNavigationBar.
Typically used with a Scaffold and a FloatingActionButton.
Scaffold(
bottomNavigationBar: BottomAppBar(
color: Colors.white,
child: bottomAppBarContents,
),
floatingActionButton: const FloatingActionButton(onPressed: null),
)
This example shows the BottomAppBar, which can be configured to have a notch using the BottomAppBar.shape property. This also includes an optional FloatingActionButton, which illustrates the FloatingActionButtonLocations in relation to the BottomAppBar.
To see it in action, copy and run this code snippet on DartPad.
import 'package:material_ui/material_ui.dart';
/// Flutter code sample for [BottomAppBar].
void main() {
runApp(const BottomAppBarDemo());
}
class BottomAppBarDemo extends StatefulWidget {
const BottomAppBarDemo({super.key});
@override
State createState() => _BottomAppBarDemoState();
}
class _BottomAppBarDemoState extends State<BottomAppBarDemo> {
bool _showFab = true;
bool _showNotch = true;
FloatingActionButtonLocation _fabLocation =
FloatingActionButtonLocation.endDocked;
void _onShowNotchChanged(bool value) {
setState(() {
_showNotch = value;
});
}
void _onShowFabChanged(bool value) {
setState(() {
_showFab = value;
});
}
void _onFabLocationChanged(FloatingActionButtonLocation? value) {
setState(() {
_fabLocation = value ?? FloatingActionButtonLocation.endDocked;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: const Text('Bottom App Bar Demo'),
),
body: RadioGroup<FloatingActionButtonLocation>(
groupValue: _fabLocation,
onChanged: (FloatingActionButtonLocation? value) =>
_onFabLocationChanged(value),
child: ListView(
padding: const .only(bottom: 88),
children: <Widget>[
SwitchListTile(
title: const Text('Floating Action Button'),
value: _showFab,
onChanged: _onShowFabChanged,
),
SwitchListTile(
title: const Text('Notch'),
value: _showNotch,
onChanged: _onShowNotchChanged,
),
const Padding(
padding: .all(16),
child: Text('Floating action button position'),
),
const RadioListTile<FloatingActionButtonLocation>(
title: Text('Docked - End'),
value: FloatingActionButtonLocation.endDocked,
),
const RadioListTile<FloatingActionButtonLocation>(
title: Text('Docked - Center'),
value: FloatingActionButtonLocation.centerDocked,
),
const RadioListTile<FloatingActionButtonLocation>(
title: Text('Floating - End'),
value: FloatingActionButtonLocation.endFloat,
),
const RadioListTile<FloatingActionButtonLocation>(
title: Text('Floating - Center'),
value: FloatingActionButtonLocation.centerFloat,
),
],
),
),
floatingActionButton: _showFab
? FloatingActionButton(
onPressed: () {},
tooltip: 'Create',
child: const Icon(Icons.add),
)
: null,
floatingActionButtonLocation: _fabLocation,
bottomNavigationBar: _DemoBottomAppBar(
fabLocation: _fabLocation,
shape: _showNotch ? const CircularNotchedRectangle() : null,
),
),
);
}
}
class _DemoBottomAppBar extends StatelessWidget {
const _DemoBottomAppBar({
this.fabLocation = FloatingActionButtonLocation.endDocked,
this.shape = const CircularNotchedRectangle(),
});
final FloatingActionButtonLocation fabLocation;
final NotchedShape? shape;
static final List<FloatingActionButtonLocation> centerLocations =
<FloatingActionButtonLocation>[
FloatingActionButtonLocation.centerDocked,
FloatingActionButtonLocation.centerFloat,
];
@override
Widget build(BuildContext context) {
return BottomAppBar(
shape: shape,
color: Colors.blue,
child: IconTheme(
data: IconThemeData(color: Theme.of(context).colorScheme.onPrimary),
child: Row(
children: <Widget>[
IconButton(
tooltip: 'Open navigation menu',
icon: const Icon(Icons.menu),
onPressed: () {},
),
if (centerLocations.contains(fabLocation)) const Spacer(),
IconButton(
tooltip: 'Search',
icon: const Icon(Icons.search),
onPressed: () {},
),
IconButton(
tooltip: 'Favorite',
icon: const Icon(Icons.favorite),
onPressed: () {},
),
],
),
),
);
}
}
This example shows Material 3 BottomAppBar with its expected look and behaviors.
This also includes an optional FloatingActionButton, which illustrates the FloatingActionButtonLocation.endContained.
To see it in action, copy and run this code snippet on DartPad.
import 'package:flutter/rendering.dart';
import 'package:material_ui/material_ui.dart';
/// Flutter code sample for [BottomAppBar] with Material 3.
void main() {
runApp(const BottomAppBarDemo());
}
class BottomAppBarDemo extends StatefulWidget {
const BottomAppBarDemo({super.key});
@override
State createState() => _BottomAppBarDemoState();
}
class _BottomAppBarDemoState extends State<BottomAppBarDemo> {
static const List<Color> colors = <Color>[
Colors.yellow,
Colors.orange,
Colors.pink,
Colors.purple,
Colors.cyan,
];
static final List<Widget> items = List<Widget>.generate(
colors.length,
(int index) => Container(color: colors[index], height: 150.0),
).reversed.toList();
late ScrollController _controller;
bool _showFab = true;
bool _isElevated = true;
bool _isVisible = true;
FloatingActionButtonLocation get _fabLocation => _isVisible
? FloatingActionButtonLocation.endContained
: FloatingActionButtonLocation.endFloat;
void _listen() {
switch (_controller.position.userScrollDirection) {
case ScrollDirection.idle:
break;
case ScrollDirection.forward:
_show();
case ScrollDirection.reverse:
_hide();
}
}
void _show() {
if (!_isVisible) {
setState(() => _isVisible = true);
}
}
void _hide() {
if (_isVisible) {
setState(() => _isVisible = false);
}
}
void _onShowFabChanged(bool value) {
setState(() {
_showFab = value;
});
}
void _onElevatedChanged(bool value) {
setState(() {
_isElevated = value;
});
}
void _addNewItem() {
setState(() {
items.insert(
0,
Container(color: colors[items.length % 5], height: 150.0),
);
});
}
@override
void initState() {
super.initState();
_controller = ScrollController();
_controller.addListener(_listen);
}
@override
void dispose() {
_controller.removeListener(_listen);
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Bottom App Bar Demo')),
body: Column(
children: <Widget>[
SwitchListTile(
title: const Text('Floating Action Button'),
value: _showFab,
onChanged: _onShowFabChanged,
),
SwitchListTile(
title: const Text('Bottom App Bar Elevation'),
value: _isElevated,
onChanged: _onElevatedChanged,
),
Expanded(
child: ListView(
controller: _controller,
children: items.toList(),
),
),
],
),
floatingActionButton: _showFab
? FloatingActionButton(
onPressed: _addNewItem,
tooltip: 'Add New Item',
elevation: _isVisible ? 0.0 : null,
child: const Icon(Icons.add),
)
: null,
floatingActionButtonLocation: _fabLocation,
bottomNavigationBar: _DemoBottomAppBar(
isElevated: _isElevated,
isVisible: _isVisible,
),
),
);
}
}
class _DemoBottomAppBar extends StatelessWidget {
const _DemoBottomAppBar({required this.isElevated, required this.isVisible});
final bool isElevated;
final bool isVisible;
@override
Widget build(BuildContext context) {
return AnimatedContainer(
duration: const Duration(milliseconds: 200),
height: isVisible ? 80.0 : 0,
child: BottomAppBar(
elevation: isElevated ? null : 0.0,
child: Row(
children: <Widget>[
IconButton(
tooltip: 'Open popup menu',
icon: const Icon(Icons.more_vert),
onPressed: () {
final SnackBar snackBar = SnackBar(
content: const Text('Yay! A SnackBar!'),
action: SnackBarAction(label: 'Undo', onPressed: () {}),
);
// Find the ScaffoldMessenger in the widget tree
// and use it to show a SnackBar.
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
),
IconButton(
tooltip: 'Search',
icon: const Icon(Icons.search),
onPressed: () {},
),
IconButton(
tooltip: 'Favorite',
icon: const Icon(Icons.favorite),
onPressed: () {},
),
],
),
),
);
}
}
See also:
- NotchedShape which calculates the notch for a notched BottomAppBar.
- FloatingActionButton which the BottomAppBar makes a notch for.
- AppBar for a toolbar that is shown at the top of the screen.
- Inheritance
-
- Object
- DiagnosticableTree
- Widget
- StatefulWidget
- BottomAppBar
Constructors
- BottomAppBar({Key? key, Color? color, double? elevation, NotchedShape? shape, Clip clipBehavior = Clip.none, double notchMargin = 4.0, Widget? child, EdgeInsetsGeometry? padding, Color? surfaceTintColor, Color? shadowColor, double? height})
-
Creates a bottom application bar.
const
Properties
- child → Widget?
-
The widget below this widget in the tree.
final
- clipBehavior → Clip
-
The content will be clipped (or not) according to this option.
final
- color → Color?
-
The bottom app bar's background color.
final
- elevation → double?
-
The z-coordinate at which to place this bottom app bar relative to its
parent.
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- height → double?
-
The double value used to indicate the height of the BottomAppBar.
final
- key → Key?
-
Controls how one widget replaces another widget in the tree.
finalinherited
- notchMargin → double
-
The margin between the FloatingActionButton and the BottomAppBar's
notch.
final
- padding → EdgeInsetsGeometry?
-
The amount of space to surround the child inside the bounds of the BottomAppBar.
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- shadowColor → Color?
-
The color of the shadow below the app bar.
final
- shape → NotchedShape?
-
The notch that is made for the floating action button.
final
- surfaceTintColor → Color?
-
A custom color for the Material 3 surface-tint elevation effect.
final
Methods
-
createElement(
) → StatefulElement -
Creates a StatefulElement to manage this widget's location in the tree.
inherited
-
createState(
) → State< StatefulWidget> -
Creates the mutable state for this widget at a given location in the tree.
override
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children.
inherited
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node.
inherited
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toDiagnosticsNode(
{String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode -
Returns a debug representation of the object that is used by debugging
tools and by DiagnosticsNode.toStringDeep.
inherited
-
toString(
{DiagnosticLevel minLevel = DiagnosticLevel.info}) → String -
A string representation of this object.
inherited
-
toStringDeep(
{String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String -
Returns a string representation of this node and its descendants.
inherited
-
toStringShallow(
{String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String -
Returns a one-line detailed description of the object.
inherited
-
toStringShort(
) → String -
A short, textual description of this widget.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited