I am using the persistent_bottom_nav_bar package and have implemented it as outlined in their Readme. Please refer to the main.dart code below.
The issue: On page1, I can navigate in to a sub-page that contains a ListView. When on that sub-page, if I don't pop that page but just directly tap on the bottom navigation items to change page, that ListView on the the sub-page continues to rebuild for every tab that I navigate to. Not sure how to prevent that from happening??
In my actual implementation (the below is a simplified code), this sub-page is a stateful widget. I therefore tried to extend the stateful widget with AutomaticKeepAliveClientMixin to not rebuild the page, but that didn't help. In the example I've given here, the sub-page is in fact a stateless widget and the issue still happens. So I suspect it stems from the package itself and not whether the page is stateful or stateless.
Anyone who might have any ideas of what's going on? Thanks in advance.
main.dart
import 'package:flutter/material.dart';
import 'package:persistent_bottom_nav_bar/persistent-tab-view.dart';
import 'page1.dart';
import 'page2.dart';
import 'page3.dart';
import 'page4.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Demo',
home: HomeScaffold(),
);
}
}
class HomeScaffold extends StatefulWidget {
@override
_HomeScaffoldState createState() => _HomeScaffoldState();
}
class _HomeScaffoldState extends State<HomeScaffold> {
PersistentTabController _controller;
@override
void initState() {
super.initState();
_controller = PersistentTabController(initialIndex: 0);
}
List<Widget> _buildScreens() {
return [
Page1(),
Page2(),
Page3(),
Page4(),
];
}
List<PersistentBottomNavBarItem> _navBarsItems() {
return [
_buildBottomNavBarItem('Page 1', Icons.home),
_buildBottomNavBarItem('Page 2', Icons.search),
_buildBottomNavBarItem('Page 3', Icons.message),
_buildBottomNavBarItem('Page 4', Icons.settings),
];
}
@override
Widget build(BuildContext context) {
return PersistentTabView(
context,
controller: _controller,
screens: _buildScreens(),
items: _navBarsItems(),
confineInSafeArea: true,
backgroundColor: Colors.white,
handleAndroidBackButtonPress: true,
resizeToAvoidBottomInset: true,
stateManagement: true,
// hideNavigationBar: true,
hideNavigationBarWhenKeyboardShows: true,
decoration: NavBarDecoration(
borderRadius: BorderRadius.circular(5.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.style8,
);
}
}
PersistentBottomNavBarItem _buildBottomNavBarItem(String title, IconData icon) {
return PersistentBottomNavBarItem(
icon: Icon(icon),
title: title,
activeColorPrimary: Colors.indigo,
inactiveColorPrimary: Colors.grey,
);
}
page1.dart
import 'page1_sub_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Page1 extends StatefulWidget {
@override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
print('Building Page1');
super.build(context);
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(child: Text('Page1')),
SizedBox(height: 40),
RaisedButton(
onPressed: () => Navigator.of(context).push(
CupertinoPageRoute(builder: (BuildContext context) => Page1SubPage()),
),
child: Text('Sub-page'),
),
],
),
);
}
}
page1_sub_page.dart
import 'package:flutter/material.dart';
class Page1SubPage extends StatelessWidget {
// Generate dummy list
final List dummyList = List.generate(100, (index) {
return {
"id": index,
"title": "This is the tile $index",
};
});
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ListView.builder(
itemCount: dummyList.length,
itemBuilder: (context, index) {
print('Building tile $index');
return Card(
elevation: 6,
margin: EdgeInsets.all(10),
child: ListTile(
leading: CircleAvatar(
child: Text(dummyList[index]["id"].toString()),
backgroundColor: Colors.purple,
),
title: Text(dummyList[index]["title"]),
),
);
} ,
)));
}
}