I'm building an app which contains bottomnaviationbaritem, Currently there are two tab items (Home Page and Search Page) and in search page there is a button.
So what i want to do is if i click on the button in Search Page i want to call open homepage and homepage bar item should be selected just like an open the app from scratch or from starting. So how to achieve this because i tried this code navigator.pushreplacement which displays two bottom navigation bar at the bottom. I hope you understand my question.
main.dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: App(),
);
}
}
class App extends StatefulWidget {
@override
State<StatefulWidget> createState() => AppState();
}
class AppState extends State<App> {
static int currentTab = 0;
final List<TabItem> tabs = [
TabItem(
tabName: "Home",
icon: Icons.home_outlined,
page: HomePage(),
),
TabItem(
tabName: "Search",
icon: Icons.search,
page: SearchPage(),
),
];
AppState() {
tabs.asMap().forEach((index, details) {
details.setIndex(index);
});
}
void _selectTab(int index) {
if (index == currentTab) {
tabs[index].key.currentState!.popUntil((route) => route.isFirst);
} else {
setState(() => currentTab = index);
}
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
final isFirstRouteInCurrentTab =
!await tabs[currentTab].key.currentState!.maybePop();
if (isFirstRouteInCurrentTab) {
if (currentTab != 0) {
_selectTab(0);
return false;
}
}
return isFirstRouteInCurrentTab;
},
child: Scaffold(
body: IndexedStack(
index: currentTab,
children: tabs.map((e) => e.page).toList(),
),
bottomNavigationBar: BottomNavigation(
onSelectTab: _selectTab,
tabs: tabs,
),
),
);
}
}
BottomNavigation.dart
class BottomNavigation extends StatelessWidget {
BottomNavigation({
required this.onSelectTab,
required this.tabs,
});
final ValueChanged<int> onSelectTab;
final List<TabItem> tabs;
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: tabs
.map(
(e) => _buildItem(
index: e.getIndex(),
icon: e.icon,
tabName: e.tabName,
),
)
.toList(),
onTap: (index) => onSelectTab(
index,
),
);
}
BottomNavigationBarItem _buildItem(
{required int index, required IconData icon, required String tabName}) {
return BottomNavigationBarItem(
icon: Icon(
icon,
color: _tabColor(index: index),
),
title: Text(
tabName,
style: TextStyle(
color: _tabColor(index: index),
fontSize: 12,
),
),
);
}
Color _tabColor({required int index}) {
return AppState.currentTab == index
? Colors.red
: Colors.black;
}
}
TabItem.dart
class TabItem {
final String tabName;
final IconData icon;
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
int _index = 0;
late Widget _page;
TabItem({
required this.tabName,
required this.icon,
required Widget page,
}) {
_page = page;
}
void setIndex(int i) {
_index = i;
}
int getIndex() => _index;
Widget get page {
return Visibility(
visible: _index == AppState.currentTab,
maintainState: true,
child: Navigator(
key: key,
onGenerateRoute: (routeSettings) {
return MaterialPageRoute(
builder: (_) => _page,
);
},
),
);
}
}
SearchPage.dart
class SearchPage extends StatefulWidget {
const SearchPage({Key? key}) : super(key: key);
@override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: TextButton(
onPressed: () {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => App()));
},
child: Text('Switch'),
),
),
),
);
}
}