This tutorial shows you how to set the color, divider color, and the icon brightness of the system navigation bar while your Flutter application is running on the foreground.
Most of the modern Android phones come with in-display navigation buttons. Sometimes, you may want to change the navigation bar style. If your application is developed using Flutter, changing the navigation bar style can be done easily by using SystemChrome
or AnnotatedRegion
. Below are the examples.
Using SystemChrome
To set the color of the navigation bar, you can use SystemChrome.setSystemUIOverlayStyle
method. Using SystemChrome
requires you to import package:flutter/services.dart
first. The method accepts a parameter of type SystemUiOverlayStyle
which can be used to define the style of the navigation bar.
Where to call the method depends on the use case. For example, if you want to set the same style for all routes in your application, you can call the method in the main
method. If you want to have different styles for each route, you need to call the method in the respective widget.
Set Color
To set the color of the navigation bar, you need to set the systemNavigationBarColor
argument when calling the constructor of SystemUiOverlayStyle
.
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemNavigationBarColor: Colors.red,
));
Output:
Set Divider Color
For the divider color, the argument you need to pass is systemNavigationBarDividerColor
.
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemNavigationBarColor: Colors.red,
systemNavigationBarDividerColor: Colors.blue,
));
Output:
Set Brightness
You may also want to set the color of the icons on the navigation bar. To do so, you can set the systemNavigationBarIconBrightness
argument with a Brightness
enum as the value. If you set the value to Brightness.light
, the color of the icons will be set to light. Otherwise, if you set the value to Brightness.dark
, the color of the icons will be set to dark.
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemNavigationBarColor: Colors.red,
systemNavigationBarIconBrightness: Brightness.dark,
));
Output:
The style applied by SystemChrome.setSystemUIOverlayStyle
persists across different routes until the method is called again to set a different style or if another widget sets the SystemUIOverlayStyle
. Beware that you may get unexpected results if the application has certain widgets such as AppBar
or CupertinoNavigationBar
as they may override the SystemUIOverlayStyle
. In that case, calling setSystemUIOverlayStyle
may have no effect. Depending on the case, we can create a workaround for that problem.
For example we are going to create a simple application that consists of two routes, both have an AppBar
and each of them has a different style for the navigation bar. Calling setSystemUIOverlayStyle
inside the build
method or the initState
may not work because the AppBar
also sets the SystemUIOverlayStyle
. One of the possible solutions is by calling the method after the build completes which can be done by putting the code inside WidgetsBinding.instance.addPostFrameCallback
.
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
SystemChrome.setSystemUIOverlayStyle(overlayStyle);
});
}
Full Code
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Woolha.com Flutter Tutorial',
initialRoute: '/one',
routes: {
'/one': (context) => PageOne(),
'/two': (context) => PageTwo(),
},
);
}
}
class PageOne extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _PageOneState();
}
}
class _PageOneState extends State<PageOne> {
static const SystemUiOverlayStyle overlayStyle = SystemUiOverlayStyle(
systemNavigationBarColor: Colors.red,
systemNavigationBarIconBrightness: Brightness.light,
systemNavigationBarDividerColor: Colors.blue,
);
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
SystemChrome.setSystemUIOverlayStyle(overlayStyle);
});
}
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(overlayStyle);
return Scaffold(
appBar: AppBar(
title: const Text('Woolha.com Flutter Tutorial'),
backgroundColor: Colors.teal,
),
body: SizedBox.expand(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Woolha.com - One', style: const TextStyle(color: Colors.black)),
OutlinedButton(
child: const Text('Go to PageTwo'),
onPressed: () {
Navigator.popAndPushNamed(context, "/two");
},
),
],
),
),
);
}
}
class PageTwo extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _PageTwoState();
}
}
class _PageTwoState extends State<PageTwo> {
static const SystemUiOverlayStyle overlayStyle = SystemUiOverlayStyle(
systemNavigationBarColor: Colors.yellow,
systemNavigationBarIconBrightness: Brightness.dark,
systemNavigationBarDividerColor: Colors.brown,
);
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
SystemChrome.setSystemUIOverlayStyle(overlayStyle);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Woolha.com Flutter Tutorial'),
backgroundColor: Colors.teal,
),
body: SizedBox.expand(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Woolha.com - Two', style: const TextStyle(color: Colors.black)),
OutlinedButton(
child: const Text('Go to PageOne'),
onPressed: () {
Navigator.popAndPushNamed(context, "/one");
},
),
],
),
),
);
}
}
Output:
Using AnnotatedRegion
Another way to set the navigation bar style is by using AnnotatedRegion
, which is a class with a generic type T extends Object
. It's used to annotate a region of the layer tree with a value whose type is T
. Therefore, we can create an AnnotatedRegion
with SystemUiOverlayStyle
as the generic type (AnnotatedRegion<SystemUiOverlayStyle>
)
const AnnotatedRegion({
Key? key,
required Widget child,
required T value,
bool sized = true,
})
For setting SystemUiOverlayStyle
using AnnotatedRegion
, you are required to pass a SystemUiOverlayStyle
as the value
argument and a Widget
as the child
argument. That means you need to create a customized SystemUiOverlayStyle
instance. Since we also use SystemUiOverlayStyle
to define the style, the name and type of the arguments used to change the navigation bar style are basically the same as the respective arguments used on the previous section which uses SystemChrome
.
Set Color
To change the color of the navigation bar, you need to set the systemNavigationBarColor
argument.
AnnotatedRegion(
value: SystemUiOverlayStyle(
systemNavigationBarColor: Colors.purple,
),
child: Scaffold(
// ...
)
)
Output:
Set Divider Color
To change the divider color, you need to set the systemNavigationBarDividerColor
argument.
AnnotatedRegion(
value: SystemUiOverlayStyle(
systemNavigationBarColor: Colors.purple,
systemNavigationBarDividerColor: Colors.green,
),
child: Scaffold(
// ...
)
)
Output:
Set Brightness
To set the brightness of the icons color, you need to set the systemNavigationBarIconBrightness
argument. If you set the value to Brightness.light
, the color of the icons will be set to light. Otherwise, if you set the value to Brightness.dark
, the color of the icons will be set to dark.
AnnotatedRegion(
value: SystemUiOverlayStyle(
systemNavigationBarColor: Colors.purple,
systemNavigationBarIconBrightness: Brightness.light,
),
child: Scaffold(
// ...
)
)
Output:
The change applied by AnnotatedRegion
persists across different routes until another widget overrides the SystemUiOverlayStyle
and changes the navigation bar style. Unlike using SystemChrome
which doesn't work if the page has an AppBar
, using AnnotatedRegion
does work to set the navigation bar on a page with AppBar
, without any workaround.
Full Code
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Woolha.com Flutter Tutorial',
initialRoute: '/one',
routes: {
'/one': (context) => PageOne(),
'/two': (context) => PageTwo(),
},
);
}
}
class PageOne extends StatelessWidget {
static const SystemUiOverlayStyle overlayStyle = SystemUiOverlayStyle(
systemNavigationBarColor: Colors.red,
systemNavigationBarIconBrightness: Brightness.light,
systemNavigationBarDividerColor: Colors.blue,
);
@override
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: overlayStyle,
child: Scaffold(
appBar: AppBar(
title: const Text('Woolha.com Flutter Tutorial'),
backgroundColor: Colors.teal,
),
body: SizedBox.expand(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Woolha.com - One', style: const TextStyle(color: Colors.black)),
OutlinedButton(
child: const Text('Go to PageTwo'),
onPressed: () {
Navigator.popAndPushNamed(context, "/two");
},
),
],
),
),
),
);
}
}
class PageTwo extends StatelessWidget {
static const SystemUiOverlayStyle overlayStyle = SystemUiOverlayStyle(
systemNavigationBarColor: Colors.purple,
systemNavigationBarIconBrightness: Brightness.dark,
systemNavigationBarDividerColor: Colors.green,
);
@override
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: overlayStyle,
child: Scaffold(
appBar: AppBar(
title: const Text('Woolha.com Flutter Tutorial'),
backgroundColor: Colors.teal,
),
body: SizedBox.expand(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Woolha.com - Two', style: const TextStyle(color: Colors.black)),
OutlinedButton(
child: const Text('Go to PageOne'),
onPressed: () {
Navigator.popAndPushNamed(context, "/one");
},
),
],
),
),
),
);
}
}
Output:
Summary
That's how to change the system navigation bar style for a Flutter application. You can use either SystemChrome
or AnnotatedRegion
.
You can also read about: