1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| class TabNavigator extends StatelessWidget { final String tabItem; final GlobalKey<NavigatorState> navigatorKey;
const TabNavigator({ Key? key, required this.tabItem, required this.navigatorKey, }) : super(key: key);
@override Widget build(BuildContext context) { return Navigator( key: navigatorKey, initialRoute: '/', onGenerateRoute: (settings) { Widget child; switch (settings.name) { case '/': child = getTabScreen(tabItem); break; case '/detail': child = DetailScreen(); break; default: child = getTabScreen(tabItem); } return MaterialPageRoute(builder: (context) => child); }, ); }
Widget getTabScreen(String tabItem) { switch (tabItem) { case 'home': return HomeScreen(); case 'profile': return ProfileScreen(); default: return HomeScreen(); } } }
class MainScreen extends StatefulWidget { @override _MainScreenState createState() => _MainScreenState(); }
class _MainScreenState extends State<MainScreen> { String _currentTab = 'home'; final Map<String, GlobalKey<NavigatorState>> _navigatorKeys = { 'home': GlobalKey<NavigatorState>(), 'profile': GlobalKey<NavigatorState>(), };
void _selectTab(String tabItem) { if (tabItem == _currentTab) { _navigatorKeys[tabItem]?.currentState?.popUntil((route) => route.isFirst); } else { setState(() => _currentTab = tabItem); } }
@override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { final isFirstRouteInCurrentTab = !await _navigatorKeys[_currentTab]!.currentState!.maybePop(); if (isFirstRouteInCurrentTab) { if (_currentTab != 'home') { _selectTab('home'); return false; } } return isFirstRouteInCurrentTab; }, child: Scaffold( body: Stack(children: [ _buildOffstageNavigator('home'), _buildOffstageNavigator('profile'), ]), bottomNavigationBar: BottomNavigationBar( currentIndex: ['home', 'profile'].indexOf(_currentTab), onTap: (index) => _selectTab(['home', 'profile'][index]), items: [ BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'), ], ), ), ); }
Widget _buildOffstageNavigator(String tabItem) { return Offstage( offstage: _currentTab != tabItem, child: TabNavigator( tabItem: tabItem, navigatorKey: _navigatorKeys[tabItem]!, ), ); } }
|