I have a Flutter app that has a BottomNavigationBar
with two tabs: Home and Profile. Profile has a ListView
containing the basic profile info and a GridView
of posts. When switching between the two tabs, I want the scroll position of the ListView
to persist. I am using PageStorageKey
to do this (as pointed out by other StackOverflow answers: e.g. here) but it doesn't give the desired result as shown by this gif:
Two things are wrong:
- When returning to the Profile tab the position is recovered but it does so by scrolling to this position;
- When leaving the Profile tab again (without any further scrolling) it causes the
ListView
to begin at the top when revisiting the Profile tab again.
How do I fix these problems?
Here is the relevant code:
// Tab navigation
class NavigatorScreen extends StatefulWidget {
@override
_NavigatorScreenState createState() => _NavigatorScreenState();
}
class _NavigatorScreenState extends State<NavigatorScreen> {
var _selectedIndex = 0;
final _bucket = PageStorageBucket();
final _screens = List<Widget>.unmodifiable([
HomeScreen(key: PageStorageKey('home')),
ProfileScreen(key: PageStorageKey('profile')),
]);
void _onItemTapped(int index) {
setState(() => _selectedIndex = index);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageStorage(
child: _screens[_selectedIndex],
bucket: _bucket,
),
bottomNavigationBar: BottomNavigationBar(
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
),
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
),
);
}
}
// Profile tab content
class ProfileScreen extends StatelessWidget {
const ProfileScreen({required Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Profile'),
),
body: ListView(
key: PageStorageKey('profileList'),
children: [
Padding(
padding: EdgeInsets.all(16.0),
child: Column(
children: [
UserDetails(),
PostStats(),
PostGrid(), // GridView.builder()
],
),
),
],
),
);
}
}