Reputation: 107
I used BottomNavigationBar
for bottom bar which changes the current index page
but I have some issue with the navigation. When I change the image on any screen, the changes show on inner pages but not show on that pages with navigate through BottomNavigationBar
and I think that's because it only changes the current state, and just pops the widget
But I need to load build context
of that page which navigate through BottomNavigationBar
, so please help with this
Here is my code:-
Bottom Bar Class
class PersistentBottomBarScaffold extends StatefulWidget {
/// pass the required items for the tabs and BottomNavigationBar
final List<PersistentTabItem> items;
const PersistentBottomBarScaffold({Key? key, required this.items})
: super(key: key);
@override
_PersistentBottomBarScaffoldState createState() =>
_PersistentBottomBarScaffoldState();
}
class _PersistentBottomBarScaffoldState
extends State<PersistentBottomBarScaffold> {
int _selectedTab = 0;
var ctime;
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
/// Check if curent tab can be popped
if (widget.items[_selectedTab].navigatorkey?.currentState?.canPop() ??
false) {
widget.items[_selectedTab].navigatorkey?.currentState?.pop();
return false;
}
else {
// if current tab can't be popped then use the root navigator
return false;
}
},
child: Scaffold(
body: IndexedStack(
index: _selectedTab,
children: widget.items
.map((page) => Navigator(
key: page.navigatorkey,
onGenerateInitialRoutes: (navigator, initialRoute) {
return [
MaterialPageRoute(builder: (context) => page.tab)
];
},
))
.toList(),
),
bottomNavigationBar: BottomNavigationBar(
backgroundColor: white,
currentIndex: _selectedTab,
selectedItemColor: Colors.pink,
unselectedItemColor: Colors.purple,
unselectedLabelStyle: TextStyle(color: Colors.purple),
type: BottomNavigationBarType.fixed,
selectedIconTheme: IconThemeData(color: Colors.pink),
onTap: (index) {
if (index == _selectedTab) {
widget.items[index].navigatorkey?.currentState
?.popUntil((route) => route.isFirst);
} else {
setState(() {
_selectedTab = index;
});
//print(_selectedTab);
}
},
items: widget.items
.map((item) {
return
BottomNavigationBarItem(
icon: Icon(item.icon),
label: item.title
);
}
).toList(),
),
),
);
}
}
/// Model class that holds the tab info for the [PersistentBottomBarScaffold]
class PersistentTabItem {
final Widget tab;
final GlobalKey<NavigatorState>? navigatorkey;
final String title;
final IconData icon;
PersistentTabItem(
{required this.tab,
this.navigatorkey,
required this.title,
required this.icon,
});
}
Main Navigator page
class MainNavigator extends StatefulWidget {
MainNavigator({Key? key,}) : super(key: key);
@override
_MainNavigator createState() => _MainNavigator();
}
class _MainNavigator extends State<MainNavigator>{
final _tab1navigatorKey = GlobalKey<NavigatorState>();
final _tab2navigatorKey = GlobalKey<NavigatorState>();
final _tab3navigatorKey = GlobalKey<NavigatorState>();
int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return PersistentBottomBarScaffold(
items: [
PersistentTabItem(
tab: PageOne(),
icon: Icons.home,
title: 'home',
navigatorkey: _tab1navigatorKey,
),
PersistentTabItem(
tab: PageTwo(),
icon: Icons.currency_rupee,
title: 'expense',
navigatorkey: _tab2navigatorKey,
),
PersistentTabItem(
tab: PageThree(),
icon: Icons.person,
title: 'staff',
navigatorkey: _tab3navigatorKey,
),
],
);
}
}
My widget Pages
Page One
class PageOne extends StatelessWidget {
const PageOne({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: Text('PageOne'),
),
),
);
}
}
Page Two
class PageTwo extends StatelessWidget {
const PageTwo({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: Text('PageTwo'),
),
),
);
}
}
Page Three
class PageThree extends StatelessWidget {
const PageThree({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: Text('PageThree'),
),
),
);
}
}
I Added My Whole Code Please understand this code on PersistentBottomBarScaffold
class i add BottomNavigationBar
and on onTap it pop and just change the current state of widget i want when it change the widget it may also load the their build conext so that i chnage something on any page or class One Two Three they show me the changes
Please if any one understand it help me with this Thank You
Upvotes: 1
Views: 305
Reputation: 5620
This might be happening because your code is using Stateless widgets instead of stateful widgets.
Try the following:
final StatefulWidget tab;
With these modifications, the state of each tab will be preserved even if you navigate to another tab and come back.
Here's the full code:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData.dark(),
home: const MainNavigator(),
);
}
}
class MainNavigator extends StatefulWidget {
const MainNavigator({
Key? key,
}) : super(key: key);
@override
_MainNavigator createState() => _MainNavigator();
}
class _MainNavigator extends State<MainNavigator> {
final _tab1navigatorKey = GlobalKey<NavigatorState>();
final _tab2navigatorKey = GlobalKey<NavigatorState>();
final _tab3navigatorKey = GlobalKey<NavigatorState>();
@override
Widget build(BuildContext context) {
return PersistentBottomBarScaffold(
items: [
PersistentTabItem(
tab: const PageOne(),
icon: Icons.home,
title: 'home',
navigatorkey: _tab1navigatorKey,
),
PersistentTabItem(
tab: const PageTwo(),
icon: Icons.currency_rupee,
title: 'expense',
navigatorkey: _tab2navigatorKey,
),
PersistentTabItem(
tab: const PageThree(),
icon: Icons.person,
title: 'staff',
navigatorkey: _tab3navigatorKey,
),
],
);
}
}
class PersistentBottomBarScaffold extends StatefulWidget {
/// pass the required items for the tabs and BottomNavigationBar
final List<PersistentTabItem> items;
const PersistentBottomBarScaffold({Key? key, required this.items})
: super(key: key);
@override
_PersistentBottomBarScaffoldState createState() =>
_PersistentBottomBarScaffoldState();
}
class _PersistentBottomBarScaffoldState
extends State<PersistentBottomBarScaffold> {
int _selectedTab = 0;
var ctime;
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
/// Check if curent tab can be popped
if (widget.items[_selectedTab].navigatorkey?.currentState?.canPop() ??
false) {
widget.items[_selectedTab].navigatorkey?.currentState?.pop();
return false;
} else {
// if current tab can't be popped then use the root navigator
return false;
}
},
child: Scaffold(
body: IndexedStack(
index: _selectedTab,
children: widget.items.map((page) => page.tab).toList(),
),
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.white,
currentIndex: _selectedTab,
selectedItemColor: Colors.pink,
unselectedItemColor: Colors.purple,
unselectedLabelStyle: const TextStyle(color: Colors.purple),
type: BottomNavigationBarType.fixed,
selectedIconTheme: const IconThemeData(color: Colors.pink),
onTap: (index) {
setState(() {
_selectedTab = index;
});
},
items: widget.items.map((item) {
return BottomNavigationBarItem(
icon: Icon(item.icon), label: item.title);
}).toList(),
),
),
);
}
}
/// Model class that holds the tab info for the [PersistentBottomBarScaffold]
class PersistentTabItem {
final StatefulWidget tab;
final GlobalKey<NavigatorState>? navigatorkey;
final String title;
final IconData icon;
PersistentTabItem({
required this.tab,
this.navigatorkey,
required this.title,
required this.icon,
});
}
class MyWidget extends StatefulWidget {
const MyWidget({super.key});
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
class PageOne extends StatefulWidget {
const PageOne({Key? key}) : super(key: key);
@override
State<PageOne> createState() => _PageOneState();
}
class _PageOneState extends State<PageOne> {
// Add your state variables and methods here
// ...
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('PageOne'),
),
);
}
}
class PageTwo extends StatefulWidget {
const PageTwo({Key? key}) : super(key: key);
@override
State<PageTwo> createState() => _PageTwoState();
}
class _PageTwoState extends State<PageTwo> {
// Add your state variables and methods here
// ...
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('PageTwo'),
),
);
}
}
class PageThree extends StatefulWidget {
const PageThree({Key? key}) : super(key: key);
@override
State<PageThree> createState() => _PageThreeState();
}
class _PageThreeState extends State<PageThree> {
// Add your state variables and methods here
// ...
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('PageThree'),
),
);
}
}
Also, you might want to use a library to manage your state for your app eg:
PS: More details on how your code is managing the state would be helpful, but this should be sufficient to solve your immediate issues.
I played with your code a bit, and this is how it looks.
Upvotes: 0