I am new to flutter and am creating my first application. It has a couple onboarding screens, and then after authentication takes the user to a StatefulShellRoute.indexedStack() which wraps child pages in a wrapper widget with a bottom nav bar (I call it TabBarNavigationPage). In this wrapper widget, I build a scaffold with a bottom nav bar and an appbar as well since i want the app bar visible on all authenticated pages in the app.
class _TabBarNavigationPageState extends State<TabBarNavigationPage> {
final List<String> appBarTitles = ['Videos', 'Profile'];
final List<String> poppableRoutes = ['/videos/single-video'];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(appBarTitles[widget.child.currentIndex]),
centerTitle: true,
actions: const [
Padding(
padding: EdgeInsets.only(right: 20.0),
child: ImageIcon(
AssetImage('assets/images/logo.png'),
color: Color.fromRGBO(245, 144, 66, 1),
size: 40,
),
),
],
leading: poppableRoutes.contains(GoRouterState.of(context).fullPath)
? IconButton(onPressed: () => context.pop(), icon: const Icon(Icons.arrow_back))
: null),
body: SafeArea(
child: widget.child,
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: widget.child.currentIndex,
onTap: (index) {
widget.child.goBranch(
index,
initialLocation: index == widget.child.currentIndex,
);
setState(() {});
},
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.play_arrow), label: 'Videos'),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle), label: 'Profile')
],
),
);
}
}
For context, here is my StatefulShellRoute.indexedStack:
StatefulShellRoute.indexedStack(
parentNavigatorKey: rootNavigatorKey,
branches: [
StatefulShellBranch(
navigatorKey: videosNavigatorKey,
initialLocation: '/videos',
routes: [
GoRoute(
path: '/videos',
name: 'videos',
routes: [
GoRoute(
path: 'single-video',
name: 'single-video',
pageBuilder: (context, state) {
return getPage(
child: const SingleVideoScreen(),
state: state);
}),
],
pageBuilder: (context, state) {
return getPage(
child: const VideosScreen(), state: state);
}),
]),
StatefulShellBranch(navigatorKey: profileNavigatorKey, routes: [
GoRoute(
path: '/profile',
name: 'profile',
pageBuilder: (context, state) {
return getPage(
child: const ProfileScreen(), state: state);
})
])
],
pageBuilder: (context, state, navigationShell) {
return getPage(
child: TabBarNavigationPage(child: navigationShell),
state: state);
})
In the ‘Videos’ branch of my StatefulShellRoute, I have a ‘single-video’ screen which is pushed onto the current navigation stack using context.go(), so I need to have a back button to take a user back to the main videos page.
My question is, is this a correct way to set up a common app bar and back button? I am doubting this approach due to my weird way of deciding whether or not to display a ‘back’ button in the TabBarNavigationPage, as checking to see if the current route is poppable based on a hardcoded list is hacky.
Based on Flutter docs for AppBar and BackButton, I tried a series of solutions of explicitly providing BackButton, not providing it and setting automaticallyImplyLeading to true, and using context.push() instead of context.go().
Mrinal Chanshetty is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.