Reputation: 167
My app has two tabs and switching the tabs doesn't keep its state. I searched the web and found to use AutomaticKeepAliveClientMixin
with wantKeepAlive
as true
and super.build(context)
. I did exactly what was told by other users across the web and stackoverflow but the problem still exists.
Here is my code:
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with AutomaticKeepAliveClientMixin{
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context);
return MaterialApp(
title: 'Flutter GridView',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.blue,
accentColor: Colors.white,
),
home: DefaultTabController(
length: 2,
child: Scaffold(
drawer: Drawer(),
backgroundColor: Colors.blueAccent,
appBar: AppBar(
backgroundColor: Colors.blueAccent,
title: Text('AIO'),
bottom: TabBar(
tabs: <Widget>[
Tab(icon: Icon(Icons.search)),
Tab(icon: Icon(Icons.favorite)),
],
),
),
body: TabBarView(
children: <Widget>[
gridView,
SecondPage(),
],
),
),
),
);
}}
Upvotes: 1
Views: 2581
Reputation: 13860
You should use KeepAliveStateMixin
in tab level. here is complete example:
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 const MaterialApp(
title: 'Flutter Demo',
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
bottomNavigationBar: const TabBar(
tabs: [
Tab(icon: Icon(Icons.home)),
Tab(icon: Icon(Icons.settings)),
Tab(icon: Icon(Icons.person)),
],
),
body: TabBarView(children: [
const CounterTab(
//key: PageStorageKey('COUNTER'),
),
Container(
color: Colors.green,
),
Container(
color: Colors.blue,
),
]),
),
);
}
}
class CounterTab extends StatefulWidget {
const CounterTab({super.key});
@override
State<CounterTab> createState() => _CounterTabState();
}
class _CounterTabState extends State<CounterTab>
with AutomaticKeepAliveClientMixin {
int _counter = 0;
@override
void initState() {
super.initState();
print('state created');
}
@override
Widget build(BuildContext context) {
super.build(context);
return Container(
color: Colors.purple,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'$_counter',
style: const TextStyle(fontSize: 60),
),
ElevatedButton(
onPressed: () {
setState(() {
_counter++;
});
},
child: const Text('Increment'),
),
],
),
);
}
@override
bool get wantKeepAlive => true;
}
Upvotes: 0
Reputation: 1566
My issue was slightly different than OPs but I want to post it here in case anyone else is running into the same issue. If you're not using a TabBarView
(in my case I can't use TabBarView
because it doesn't seem to work with dynamically sized pages) and a Center
to hold your tab pages like this:
Center(
child: [
Page1(),
Page2(),
][_tabIndex],
)
then the AutomaticKeepAliveClientMixin that I added to Page1State
and Page2State
was not working for me. I had to use an IndexedStack
in order for it to work:
IndexedStack(
index: _tabIndex,
children: [
Page1(),
Page2()
],
)
So it looks like this:
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: TabBar(controller: _tabController, tabs: [
Tab(text: "Tab 1"),
Tab(text: "Tab 2"),
]),
),
IndexedStack(
index: _tabIndex,
children: [
Page1(),
Page2()
],
),
],
);
}
Upvotes: 0
Reputation: 11
Use PageStorage, PageStorageBucket and PageStorageKey.
Create an instance field of PageStorageBucket, wrap your TabBarView with PageStorage, then add PageStorageKey to your GridView.
class _MyAppState extends State<MyApp> {
final PageStorageBucket bucket = PageStorageBucket();
//...
body: PageStorage(
bucket: bucket,
child: TabBarView(
children: <Widget>[
gridView, // add to GridView(key: PageStorageKey('MyGridViewKey'), //...
SecondPage(),
],
),
),
//...
Upvotes: 1