PersistentBottomNavBar
PersistentBottomNavBar copied to clipboard
how i can rebuild some screen when click on PersistentBottomNavBarItem?
how i can rebuild some screen when click on PersistentBottomNavBarItem?
@ahmedhassan747474 set your state management to false and it will rebuild your screen every time you click on items.
@sailendraw hi hope u doing well, how do u mean setting state managment to false plz help me i have the same issue
hey @sailendraw can we make state management false to individual items? and for other state management true.
@ahmedhassan747474 set your state management to false and it will rebuild your screen every time you click on items.
I have set it into stateManagement: false,
but everytime I click the menu, all of the screen are rebuilt. Is there another way to only rebuild the only screen that has tapped. For example I have screen A, B, C so when I tap menu A it will rebuild screen A, not B and C also. This case is related to https://github.com/BilalShahid13/PersistentBottomNavBar/issues/268 and I open a question in https://stackoverflow.com/questions/70648849/bottom-tab-navigator-persistenttabview-rebuild-the-screen-when-user-tabs-the
@wahyu-handayani Hey, To rebuild only screen A everytime when bottom nav bar click not B and C Use this:
Inside PersistentBottomNavBarItem( OnPressed: setstate to _controller.index=0 0 represent that screen index you want to rebuild )
I also Answer this on StackOverflow if this works let me know
@hanishk There is no onPressed
property inside PersistentBottomNavBarItem
so I add setState like this:
onItemSelected: (index) {
setState(() {
_controller.index=index;
});
.......
},
but still there is no changes, it still rebuilds for all screen
Can you Share code with PersistentBottomNavBarItem Widget, make sure statemangement is true
List<PersistentBottomNavBarItem> _navBarsItems;
List<Widget> _buildScreens() {
return [DashBoardScreen(), Home(), SaveDriver(), YardGLoc(), Ads()];
}
inside initState
_navBarsItems = [
PersistentBottomNavBarItem(
onPressed: (BuildContext context) {
print("Hello");
setState(() {
_controller.index = 0;
});
},
icon: const Icon(Icons.dashboard),
title: ("Dashboard"),
activeColorPrimary: AppTheme.yellow,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
icon: Icon(CupertinoIcons.home),
title: ("Home"),
activeColorPrimary: AppTheme.yellow,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
];
setState(() {
_controller = PersistentTabController(initialIndex: currentIndex);
});
then Inside Build Method
return PersistentTabView(
context,
controller: _controller,
screens: _buildScreens(),
items: _navBarsItems,
margin: const EdgeInsets.all(0.0),
confineInSafeArea: true,
backgroundColor: AppTheme.darkBlue, // Default is Colors.white.
handleAndroidBackButtonPress: true, // Default is true.
resizeToAvoidBottomInset:
true, // This needs to be true if you want to move up the screen when keyboard appears. Default is true.
stateManagement: true, // Default is true.
// popAllScreensOnTapOfSelectedTab: true,
popAllScreensOnTapOfSelectedTab: false,
navBarHeight: MediaQuery.of(context).viewInsets.bottom > 0
? 0.0
: kBottomNavigationBarHeight,
hideNavigationBarWhenKeyboardShows:
true, // Recommended to set 'resizeToAvoidBottomInset' as true while using this argument. Default is true.
popActionScreens: PopActionScreensType.all,
decoration: const NavBarDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
topRight: Radius.circular(10.0),
),
colorBehindNavBar: Colors.white,
),
// popAllScreensOnTapOfSelectedTab: true,
itemAnimationProperties: ItemAnimationProperties(
// Navigation Bar's items animation properties.
duration: Duration(milliseconds: 200),
curve: Curves.ease,
),
screenTransitionAnimation: ScreenTransitionAnimation(
// Screen transition animation on change of selected tab.
animateTabTransition: true,
curve: Curves.ease,
duration: Duration(milliseconds: 200),
),
navBarStyle:
NavBarStyle.style3, // Choose the nav bar style with this property.
);
@hanishk here is part of thecode, I have been set statemangement into false => but the result is still rebuild for all screen, while statemangement true=> it only rebuild when I tap it once, when I tap it for second time.. it doesn't rebuild the screen
Scaffold(
body: ValueListenableBuilder(
valueListenable: mainState,
builder: (_, value, __) {
return PersistentTabView(
context,
onItemSelected: (index) {
setState(() {
_controller.index = index;
});
mainState.value = MainTabModel(
selectedIndex: index,
connectionStatus: mainState.value.connectionStatus);
if (index == 1) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
PinPayrol(statusPin: "input_pin")))
.then((x) {
if (x != null)
mainState.value = MainTabModel(
selectedIndex: index,
connectionStatus:
mainState.value.connectionStatus);
else
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BottomTab()));
mainState.notifyListeners();
});
} else
mainState.value = MainTabModel(
selectedIndex: index,
connectionStatus: mainState.value.connectionStatus);
},
controller: _controller,
screens: _buildScreens(),
items: _navBarsItems(),
confineInSafeArea: true,
backgroundColor: Colors.white,
handleAndroidBackButtonPress: true,
resizeToAvoidBottomInset: true,
stateManagement: true,
hideNavigationBarWhenKeyboardShows: true,
decoration: NavBarDecoration(
borderRadius: BorderRadius.circular(10.0),
colorBehindNavBar: Colors.white,
),
popAllScreensOnTapOfSelectedTab: true,
popActionScreens: PopActionScreensType.all,
itemAnimationProperties: ItemAnimationProperties(
duration: Duration(milliseconds: 200),
curve: Curves.ease,
),
screenTransitionAnimation: ScreenTransitionAnimation(
animateTabTransition: true,
curve: Curves.ease,
duration: Duration(milliseconds: 200),
),
navBarStyle: NavBarStyle.style15,
);
}))
Try above Code & setCurrentindex = 0 , currentIndex = 2 not callback index in each PersitentBottomNavBarItem, setmanagement to true
@hanishk I am sorry for disturbing you, I have tried your code just now, here is it: but the result is like I explain before:
statemangement into false => but the result is still rebuild for all screen, while statemangement true=> it only rebuild when I tap it once, when I tap it for second time.. it doesn't rebuild the screen
List<PersistentBottomNavBarItem> _navBarsItems() {
return [
PersistentBottomNavBarItem(
onPressed: (BuildContext context) {
setState(() {
_controller.index = 0;
});
},
icon: Icon(...),
title: ("A"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
onPressed: (BuildContext context) {
setState(() {
_controller.index = 1;
});
},
icon: Icon(...),
title: ("B"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
onPressed: (BuildContext context) {
setState(() {
_controller.index = 2;
});
},
icon: Icon(
...
),
title: ("C"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
onPressed: (BuildContext context) {
setState(() {
_controller.index = 3;
});
},
icon: Icon(...),
title: ("D"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
onPressed: (BuildContext context) {
setState(() {
_controller.index = 4;
});
},
icon: Icon(...),
title: ("E"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
];
}
Is this inside initState?
@hanishk I didn't call it inside initState, here is full of my code, would you like to take a look
class _BottomTabState extends State<BottomTab> {
DataMain singletonData = DataMain();
List<PersistentBottomNavBarItem> _navBarsItems() {
return [
PersistentBottomNavBarItem(
onPressed: (BuildContext context) {
setState(() {
_controller.index = 0;
});
},
icon: Icon(...),
title: ("A"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
onPressed: (BuildContext context) {
setState(() {
_controller.index = 1;
});
},
icon: Icon(...),
title: ("B"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
onPressed: (BuildContext context) {
setState(() {
_controller.index = 2;
});
},
icon: Icon(
...
),
title: ("C"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
onPressed: (BuildContext context) {
setState(() {
_controller.index = 3;
});
},
icon: Icon(...),
title: ("D"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
onPressed: (BuildContext context) {
setState(() {
_controller.index = 4;
});
},
icon: Icon(...),
title: ("E"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
];
}
PersistentTabController _controller =
PersistentTabController(initialIndex: 0);
List<Widget> _buildScreens() {
return [
A(),
B(source: "main"),
C(),
D(),
E()
];
}
@override
void initState() {
super.initState();}
final ValueNotifier<MainTabModel> mainState =
ValueNotifier<MainTabModel>(MainTabModel());
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return FutureProvider<String>(
create: (context) async {
.......// my content
},
child: Scaffold(
body: ValueListenableBuilder(
valueListenable: mainState,
builder: (_, value, __) {
return PersistentTabView(
context,
onItemSelected: (index) {
mainState.value = MainTabModel(
selectedIndex: index,
connectionStatus: mainState.value.connectionStatus);
if (index == 1) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
PinPayrol(statusPin: "input_pin")))
.then((x) {
if (x != null)
mainState.value = MainTabModel(
selectedIndex: index,
connectionStatus:
mainState.value.connectionStatus);
else
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BottomTab()));
mainState.notifyListeners();
});
} else
mainState.value = MainTabModel(
selectedIndex: index,
connectionStatus: mainState.value.connectionStatus);
},
controller: _controller,
screens: _buildScreens(),
items: _navBarsItems(),
confineInSafeArea: true,
backgroundColor: Colors.white,
handleAndroidBackButtonPress: true,
resizeToAvoidBottomInset: true,
stateManagement: true,
hideNavigationBarWhenKeyboardShows: true,
decoration: NavBarDecoration(
borderRadius: BorderRadius.circular(10.0),
colorBehindNavBar: Colors.white,
),
popAllScreensOnTapOfSelectedTab: true,
popActionScreens: PopActionScreensType.all,
itemAnimationProperties: ItemAnimationProperties(
duration: Duration(milliseconds: 200),
curve: Curves.ease,
),
screenTransitionAnimation: ScreenTransitionAnimation(
animateTabTransition: true,
curve: Curves.ease,
duration: Duration(milliseconds: 200),
),
navBarStyle: NavBarStyle.style15,
);
})));
}
}
Globally Declare this:
List<PersistentBottomNavBarItem> _navBarsItems;
then inside initState add return _navBarItems= [... PersitantBottomNavBarItem];
@hanishk I have tried it just now, and still there is no effect of changes I add it like this:
List<PersistentBottomNavBarItem> _navBarsItemsNew;
and then inside initState:
_navBarsItemsNew= _navBarsItems();
See my above Code you are not writing the code that i mentioned above whole code. follow step by step
then paste whole screen code
I would like to make sure, how you change your currentIndex
? when I read your code there is no something like
setState(() {
currentIndex=...;
});
because in my code I set it as static like this:
PersistentTabController(initialIndex: 0);```
Declare Globally
int current_index =0;
then inside PersitentTabController pass current_index to initialIndex
I will try it again with your code and let you know the result @hanishk
I will try it again with your code and let you know the result @hanishk
Did you get it?
@hanishk I am so sorry for my late reply, and so sorry for disturbing you. Would you like to run my code? I am following your steps with different way, but when you check the log print of this code, the screen will always rebuild. And alsoinitState
should run once when I click the menu, but here when I click the menu A (initState run) - then click B (initState B run) - then click A again (initState A doesn't run)
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:persistent_bottom_nav_bar/persistent-tab-view.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: BottomTab(),
);
}
}
class BottomTab extends StatefulWidget {
const BottomTab({Key? key}) : super(key: key);
@override
_BottomTabState createState() => _BottomTabState();
}
class _BottomTabState extends State<BottomTab> {
late PersistentTabController _controller;
List<Widget> _buildScreens() {
return [
HomeScreen(),
PayrollScreenDev(),
RevAbsensiScreen(),
PayrollScreen(),
AkunScreen()
];
}
late List<PersistentBottomNavBarItem> navBarsItemsNew;
@override
void initState() {
super.initState();
setState(() {
_controller = PersistentTabController(initialIndex: 0);
});
navBarsItemsNew = [
PersistentBottomNavBarItem(
onPressed: (context) {
setState(() {
_controller.index = 0;
});
},
icon: Icon(Icons.home),
title: ("Beranda"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
onPressed: (context) {
setState(() {
_controller.index = 1;
});
},
icon: Icon(Icons.home),
title: ("Payroll"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
icon: Icon(Icons.home),
onPressed: (context) {
setState(() {
_controller.index = 2;
});
},
title: ("Absensi"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
onPressed: (context) {
setState(() {
_controller.index = 3;
});
},
icon: Icon(Icons.home),
title: ("SINDE"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
onPressed: (context) {
setState(() {
_controller.index = 4;
});
},
icon: Icon(Icons.home),
title: ("Akun"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
];
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PersistentTabView(
context,
controller: _controller,
screens: _buildScreens(),
items: navBarsItemsNew,
confineInSafeArea: true,
backgroundColor: Colors.white,
handleAndroidBackButtonPress: true,
resizeToAvoidBottomInset: true,
stateManagement: true,
hideNavigationBarWhenKeyboardShows: true,
decoration: NavBarDecoration(
borderRadius: BorderRadius.circular(10.0),
colorBehindNavBar: Colors.white,
),
popAllScreensOnTapOfSelectedTab: true,
popActionScreens: PopActionScreensType.all,
itemAnimationProperties: ItemAnimationProperties(
duration: Duration(milliseconds: 200),
curve: Curves.ease,
),
screenTransitionAnimation: ScreenTransitionAnimation(
animateTabTransition: true,
curve: Curves.ease,
duration: Duration(milliseconds: 200),
),
navBarStyle: NavBarStyle.style15,
));
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
void initState() {
super.initState();
print("initState HomeScreen");
}
@override
Widget build(BuildContext context) {
print("HomeScreen");
return Scaffold(
body: Text("HomeScreen"),
);
}
}
class RevAbsensiScreen extends StatefulWidget {
const RevAbsensiScreen({Key? key}) : super(key: key);
@override
_RevAbsensiScreenState createState() => _RevAbsensiScreenState();
}
class _RevAbsensiScreenState extends State<RevAbsensiScreen> {
@override
void initState() {
super.initState();
print("initState RevAbsensiScreen");
}
@override
Widget build(BuildContext context) {
print("RevAbsensiScreen");
return Scaffold(
body: Text("RevAbsensiScreen"),
);
}
}
class PayrollScreen extends StatefulWidget {
const PayrollScreen({Key? key}) : super(key: key);
@override
_PayrollScreenState createState() => _PayrollScreenState();
}
class _PayrollScreenState extends State<PayrollScreen> {
@override
void initState() {
super.initState();
print("initState PayrollScreen");
}
@override
Widget build(BuildContext context) {
print("PayrollScreen");
return Scaffold(
body: Text("PayrollScreen"),
);
}
}
class AkunScreen extends StatefulWidget {
const AkunScreen({Key? key}) : super(key: key);
@override
_AkunScreenState createState() => _AkunScreenState();
}
class _AkunScreenState extends State<AkunScreen> {
@override
void initState() {
super.initState();
print("initState AkunScreen");
}
@override
Widget build(BuildContext context) {
print("AkunScreen");
return Scaffold(
body: Text("AkunScreen"),
);
}
}
class PayrollScreenDev extends StatefulWidget {
const PayrollScreenDev({Key? key}) : super(key: key);
@override
_PayrollScreenDevState createState() => _PayrollScreenDevState();
}
class _PayrollScreenDevState extends State<PayrollScreenDev> {
@override
void initState() {
super.initState();
print("initState PayrollScreenDev");
}
@override
Widget build(BuildContext context) {
print("PayrollScreenDev");
return Scaffold(
body: Text("PayrollScreenDev"),
);
}
}
@hanishk your solution does not work.
List<PersistentBottomNavBarItem> _navBarsItems;
List<Widget> _buildScreens() { return [DashBoardScreen(), Home(), SaveDriver(), YardGLoc(), Ads()]; }
inside initState
_navBarsItems = [ PersistentBottomNavBarItem( onPressed: (BuildContext context) { print("Hello"); setState(() { _controller.index = 0; }); }, icon: const Icon(Icons.dashboard), title: ("Dashboard"), activeColorPrimary: AppTheme.yellow, inactiveColorPrimary: CupertinoColors.systemGrey, ), PersistentBottomNavBarItem( icon: Icon(CupertinoIcons.home), title: ("Home"), activeColorPrimary: AppTheme.yellow, inactiveColorPrimary: CupertinoColors.systemGrey, ), ]; setState(() { _controller = PersistentTabController(initialIndex: currentIndex); });
then Inside Build Method
return PersistentTabView( context, controller: _controller, screens: _buildScreens(), items: _navBarsItems, margin: const EdgeInsets.all(0.0), confineInSafeArea: true, backgroundColor: AppTheme.darkBlue, // Default is Colors.white. handleAndroidBackButtonPress: true, // Default is true. resizeToAvoidBottomInset: true, // This needs to be true if you want to move up the screen when keyboard appears. Default is true. stateManagement: true, // Default is true. // popAllScreensOnTapOfSelectedTab: true, popAllScreensOnTapOfSelectedTab: false, navBarHeight: MediaQuery.of(context).viewInsets.bottom > 0 ? 0.0 : kBottomNavigationBarHeight, hideNavigationBarWhenKeyboardShows: true, // Recommended to set 'resizeToAvoidBottomInset' as true while using this argument. Default is true. popActionScreens: PopActionScreensType.all, decoration: const NavBarDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(10.0), topRight: Radius.circular(10.0), ), colorBehindNavBar: Colors.white, ), // popAllScreensOnTapOfSelectedTab: true, itemAnimationProperties: ItemAnimationProperties( // Navigation Bar's items animation properties. duration: Duration(milliseconds: 200), curve: Curves.ease, ), screenTransitionAnimation: ScreenTransitionAnimation( // Screen transition animation on change of selected tab. animateTabTransition: true, curve: Curves.ease, duration: Duration(milliseconds: 200), ), navBarStyle: NavBarStyle.style3, // Choose the nav bar style with this property. );
@Mamun-Lab did u try this??
any updates here? @Mamun-Lab @wahyu-handayani did you solve it?
@Abdelaty I didn't solve it, so I use another bottom tab navigator
@wahyu-handayani can you give me a link? I tried to use the provider to update the screen and it worked!
@wahyu-handayani can you give me a link? I tried to use the provider to update the screen and it worked!
Hi @Abdelaty, I find this question https://stackoverflow.com/questions/54450397/how-to-make-the-bottom-navigation-bar-overlay-the-main-page-in-flutter and it relates to my case
@wahyu-handayani can you give me a link? I tried to use the provider to update the screen and it worked!
Can you share with me how to solve this problem by provider I am also facing same issue. Initially all screen build but when we click on any tab of bottom nav it don't build again😕
Is this issue solved. Still I am facing same kind of issue. Refreshing all tabs in each click. If any working solution please help us
I solve it by adding a ternary expression on _controller.index
with the index of the widget that i want to rebuild
Example : stateManagement: (_controller.index==2) ? false : true,
Result : All other widgets will no rebuilt, only widget of index 2 will be rebuilt if PersistentBottomNavBar clicked
Note : After the rebuilt of widget with the index 2 the BottomNavBar will rebuilt all widget after